Android中关于CoordinatorLayout的一些实用布局技巧

介绍

CoordinatorLayout是一个“加强版”的 FrameLayout,它主要有两个用途:

(1) 用作应用的顶层布局管理器

(2) 通过为子View指定 behavior 实现自定义的交互行为。

在我们做 Material Design 风格的app时通常都使用 CoordinatorLayout 作为布局的根节点,以便实现特定的UI交互行为。
那么现在我们来看看如何用已有的一些控件实现一些常见的布局。

Toolbar + TabLayout 实现 TabLayout 置顶效果

很常见的一种模式是 TabLayout 放在 ToolBar 布局中与其一起置顶在界面上方,而现在的效果是将ToolBar 隐藏而 TabLayout一直置顶在界面上方。


tablayout

如何实现呢?首先所在的 Activity 要使用 AppTheme.NoActionBar 风格主题,之后再编写布局文件。

<android.support.design.widget.CoordinatorLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <android.support.design.widget.AppBarLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:theme="@style/AppTheme.AppBarOverlay">

 <android.support.v7.widget.Toolbar
  android:id="@+id/toolbar"
  android:layout_width="match_parent"
  android:layout_height="?attr/actionBarSize"
  android:background="?attr/colorPrimary"
  app:layout_scrollFlags="scroll|enterAlways|snap"
  app:popupTheme="@style/AppTheme.PopupOverlay">

  <!-- toolbar内部布局文件 -->

 </android.support.v7.widget.Toolbar>

 <android.support.design.widget.TabLayout
  android:id="@+id/tab_layout"
  android:layout_width="match_parent"
  android:layout_height="@dimen/tab_height"
  app:tabIndicatorColor="@color/white"
  app:tabTextColor="@color/white_normal">

 </android.support.design.widget.TabLayout>

 </android.support.design.widget.AppBarLayout>

 <!-- 主界面布局文件 -->

</android.support.design.widget.CoordinatorLayout>

很重要的两点:

  • 设置 Toolbar 的 layout_scrollFlags="scroll|enterAlways|snap" 保证 Toolbar 能随界面滑动向上隐藏。
  • TabLayout 与 Toolbar 同级,父节点为 AppBarLayout ,保证 TabLayout 能够能够显示在 Toolbar 外面而不随其一起隐藏。

浸入式 + CollapsingToolbarLayout

CollapsingToolbarLayout 可以包裹 Toolbar , 当其显示完收缩动画时使 Toolbar 显示在顶端。而我们可以再加入浸入式的效果让 CollapsingToolbarLayout 的背景图突破系统的状态栏使界面更加美观同时也不影响 Toolbar 的显示效果。


浸入式布局

在实现布局文件前要赋予当前的Activity主题为AppTheme.Immersive。

其样式要在 v19 与 v21 分别处理,至于v19之前的 android 版本那就无能为力了。

v19

<style name="AppTheme.Immersive" parent="AppTheme.NoActionBar">
 <item name="android:windowTranslucentStatus">true</item>
</style>

v21

<style name="AppTheme.Immersive" parent="AppTheme.NoActionBar">
 <!--透明导航栏-->
 <item name="android:statusBarColor">@android:color/transparent</item>
 <item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>

之后再来看布局文件,包括了 AppBarLayout,CollapsingToolbarLayout 和 Toolbar 这些控件。

同样也是要分为 v19 和 v21 两种布局

v19

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <android.support.design.widget.AppBarLayout
  android:id="@+id/app_bar"
  android:layout_width="match_parent"
  android:layout_height="220dp"
  android:theme="@style/AppTheme.AppBarOverlay">

  <android.support.design.widget.CollapsingToolbarLayout
   android:id="@+id/collapsing_layout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:contentScrim="?attr/colorPrimary"
   app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
   app:statusBarScrim="@android:color/transparent"
   app:titleEnabled="false">

   <RelativeLayout
    android:id="@+id/anime_root"
    android:layout_width="match_parent"
    android:layout_height="220dp"
    app:layout_collapseMode="parallax"
    app:layout_collapseParallaxMultiplier="0.7">

    <!-- 可伸缩背景图布局文件 -->

   </RelativeLayout>

   <android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:layout_marginTop="25dp"
    app:layout_collapseMode="pin"
    app:popupTheme="@style/AppTheme.PopupOverlay"
    app:titleMarginTop="15dp" />

  </android.support.design.widget.CollapsingToolbarLayout>

 </android.support.design.widget.AppBarLayout>

 <!-- 界面布局文件 -->

</android.support.design.widget.CoordinatorLayout>

v21

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:fitsSystemWindows="true">

 <android.support.design.widget.AppBarLayout
  android:id="@+id/app_bar"
  android:layout_width="match_parent"
  android:layout_height="220dp"
  android:fitsSystemWindows="true"
  android:theme="@style/AppTheme.AppBarOverlay">

  <android.support.design.widget.CollapsingToolbarLayout
   android:id="@+id/collapsing_layout"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:fitsSystemWindows="true"
   app:contentScrim="?attr/colorPrimary"
   app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
   app:statusBarScrim="@android:color/transparent"
   app:titleEnabled="false">

   <RelativeLayout
    android:id="@+id/anime_root"
    android:layout_width="match_parent"
    android:layout_height="220dp"
    android:fitsSystemWindows="true"
    app:layout_collapseMode="parallax"
    app:layout_collapseParallaxMultiplier="0.7">

    <!-- 可伸缩背景图布局文件 -->

   </RelativeLayout>

   <android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:layout_collapseMode="pin"
    app:popupTheme="@style/AppTheme.PopupOverlay"
    app:titleMarginTop="15dp" />

  </android.support.design.widget.CollapsingToolbarLayout>

 </android.support.design.widget.AppBarLayout>

 <!-- 界面布局文件 -->

</android.support.design.widget.CoordinatorLayout>

那么重点在哪里呢?

  • 设置你当前的 Activity 的状态栏为透明,4.4之前的机型则无法适配。
  • 注意每个控件下的 fitsSystemWindows 属性,使系统能够调整 view 的 padding 值使其适配。
  • 设置 CollapsingToolbarLayout 为可滚动(scroll),滚动结束后可以设置 statusBarScrim 作为覆盖色。
  • 背景布局与 Toolbar 同级,布局文件上可以设置滚动的模式,如视差滚动及相应的值。
  • 注意到 v19 的布局文件上的 Toolbar ,给它赋予了一个 android:layout_marginTop="25dp"的属性,以便在Android 4.4上时防止被系统的状态栏所覆盖。当然这个值可以在代码中获取到系统状态栏高度再进行设置。

fitsSystemWindows详解:这个一个boolean值的内部属性,让view可以根据系统窗口(如status bar)来调整自己的布局,如果值为true,就会调整view的paingding属性来给system windows留出空间。

Fragment + 不同风格布局

有时候产品要求在一个 Activity 上显示不同的 Fragment 界面,且 Fragment 上的每一个头部样式都不一样,比如说一个是普通情况下的 Toolbar,另一个却是浸入式的可伸缩头部,像简书app的首页

额,我们先不提图中的那个bug,图中的界面主要是两种效果,一个为普通的标题栏+正文,另一个则是浸入式的图片背景+正文。我们也可以利用浸入式的主题来仿照出简书的效果。


各个页面不同样式

第一步要做的是给 Fragment 所在的 Activity 套上 AppTheme.Immersive 浸入式主题样式,之后为 Activity 加上布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <com.ashokvarma.bottomnavigation.BottomNavigationBar
  android:id="@+id/bottom_navigation_bar"
  android:layout_width="match_parent"
  android:layout_height="56dp"
  android:layout_gravity="bottom"
  android:fitsSystemWindows="true">

 </com.ashokvarma.bottomnavigation.BottomNavigationBar>

 <android.support.v4.view.ViewPager
  android:id="@+id/viewpager"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:layout_marginBottom="56dp" />

</android.support.design.widget.CoordinatorLayout>

无他,就是一个 ViewPager 容器用来加载 Fragment。

书城所在的 Fragment 布局如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:fitsSystemWindows="true">

 <android.support.design.widget.AppBarLayout
  android:id="@+id/app_bar"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:fitsSystemWindows="true"
  android:theme="@style/AppTheme.AppBarOverlay">

  <android.support.design.widget.CollapsingToolbarLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:fitsSystemWindows="true"
   app:contentScrim="?attr/colorPrimary"
   app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
   app:statusBarScrim="@android:color/transparent"
   app:titleEnabled="false">

   <!-- 背景布局 -->

   <android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="36dp"
    android:minHeight="36dp"
    app:layout_collapseMode="pin"
    app:popupTheme="@style/AppTheme.PopupOverlay">
    <!-- 搜索框布局 -->

   </android.support.v7.widget.Toolbar>

  </android.support.design.widget.CollapsingToolbarLayout>

 </android.support.design.widget.AppBarLayout>

 <!-- 界面主布局 -->

</android.support.design.widget.CoordinatorLayout>

布局跟之前的浸入式布局相同,但单单这样布局是有问题的,此时的 Toolbar 会显示在系统的状态栏下。所以我们要修正 Toolbar 的摆放位置,即人为的为其设置 MarginTop 距离。

/**
 * 修正 Toolbar 的位置
 * 在 Android 4.4 版本下无法显示内容在 StatusBar 下,所以无需修正 Toolbar 的位置
 *
 * @param toolbar
 */
protected void fixToolbar(Toolbar toolbar) {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  int statusHeight = getStatusBarHeight(getActivity());
  ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) toolbar.getLayoutParams();
  layoutParams.setMargins(0, statusHeight, 0, 0);
 }
}

/**
 * 获取系统状态栏高度
 *
 * @param context
 * @return
 */
public int getStatusBarHeight(Context context) {
 Class<?> c = null;
 Object obj = null;
 Field field = null;
 int x = 0, statusBarHeight = 0;
 try {
  c = Class.forName("com.android.internal.R$dimen");
  obj = c.newInstance();
  field = c.getField("status_bar_height");
  x = Integer.parseInt(field.get(obj).toString());
  statusBarHeight = context.getResources().getDimensionPixelSize(x);
 } catch (Exception e1) {
  e1.printStackTrace();
 }
 return statusBarHeight;
}

在每个 Fragment 初始化 Toolbar 时都需要调用这个方法来修正位置。

重点又来了:

  • 修改为浸入式样式主题,要点见上一个案例。
  • 人为修正 Toolbar 的距离,保证位置摆放正确。
  • 注意 Fragment 切换时偶尔出现的一些 Toolbar 问题。

Fragment 与 Toolbar 的选项菜单问题

在 Fragment 之间切换的时候很容易遇到 Toolbar 上的菜单无法正确的显示的问题,解决方法也很简单,在 Fragment 的 onCreateView() 方法中添加一行代码:

toolbar.setTitle("title");
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
fixToolbar(toolbar);
setHasOptionsMenu(true); //重要的一行代码,防止选项菜单错乱

总结

自从 Google 出了 com.android.support:design 包之后,其多样化的定制给 App 应用带来更加酷炫的效果,布局的变化只不过是其中的一部分而已。文章的开头也说了, CoordinatorLayout 不止是带来了布局的变化,也带给了控件更多的UI交互动作。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Android 5.0中CoordinatorLayout的使用技巧

    CoordinatorLayout 实现了多种Material Design中提到的滚动效果.目前这个框架提供了几种不用写动画代码就能工作的方法,这些效果包括: *让浮动操作按钮上下滑动,为Snackbar留出空间. *扩展或者缩小Toolbar或者头部,让主内容区域有更多的空间. *控制哪个view应该扩展还是收缩,以及其显示大小比例,包括视差滚动效果动画. 浮动操作按钮与Snackbar CoordinatorLayout可以用来配合浮动操作按钮的 layout_anchor 和 layou

  • CoordinatorLayout的使用如此简单(Android)

    曾在网上找了一些关于CoordinatorLayout的教程,大部分文章都是把CoordinatorLayout.AppbarLayout.CollapsingToolbarLayout 以及Toolbar等一起使用来介绍,这让我不知不觉在心中认为把这几个布局要一起使用,而且只是用于那种场景中.其实CoordinatorLayout的功能并不是局限于与AppBarLayout一起使用,它的功能强大着呢,本文主要对CoordinatorLayout的使用进行介绍,后面再写一篇文章将AppBarLa

  • Android布局技巧之合并布局

    我们已经有文章向你描述如何使用<include />标签来重用和共享你的布局代码.这篇文章将向你阐述<merge />标签的使用以及如何与<include />标签互补使用. <merge />标签用于减少View树的层次来优化Android的布局.通过看一个例子,你就能很容易的理解这个标签能解决的问题.下面的XML布局显示一个图片,并且有一个标题位于其上方.这个结构相当的简单:FrameLayout里放置了一个ImageView,其上放置了一个TextVi

  • Android布局技巧之创建可重用的UI组件

    Android平台提供了大量的UI构件,你可以将这些小的视觉块(构件)搭建在一起,呈现给用户复杂且有用的画面.然而,应用程序有时需要一些高级的视觉组件.为了满足这一需求,并且能高效的实现,你可以把多个标准的构件结合起来成为一个单独的.可重用的组件. 例如,你可以创建一个可重用的组件包含一个进度条和一个取消按钮,一个Panel包含两个按钮(确定和取消动作),一个Panel包含图标.标题和描述等等.简单的,你可以通过书写一个自定义的View来创建一个UI组件,但更简单的方式是仅使用XML来实现. 在

  • Android布局技巧之创建高效布局

    Android UI工具包提供了一些布局管理器,它们使用起来相当容易,而且,大多数的时候,你只需要使用它们最基本的特征来实现UI. 执着于基本特征的使用对于创建UI来说,往往不是最高效的.一个常见的例子就是滥用LinearLayout,它将会导致View树中的View数量激增.View--更糟的是,布局管理器--添加到应用程序里都会带来一定的消耗:初始化,布局和绘制变得更加缓慢.嵌套布局的花销尤其"昂贵",例如,如果你嵌套了一些LinearLayout,并使用了weight参数,这会导

  • Android Studio使用小技巧:布局预览时填充数据

    我们都知道Android Studio用起来很棒,其中布局预览更棒.我们在调UI的时候基本是需要实时预览来看效果的,在Android Studio中只需要切换到Design就可以看到,而且我们需要在布局上填充数据预览效果更好,比如我们在TextView中设定text属性来看下字体大小与布局是否正确,但是呢正式环境我们又需要移除这些额外的数据,不然看着很不舒服,这个时候就用到了本篇博客介绍的一个技巧. 废话不多说,直接上图: 上述示例中只需要在xml布局文件中添加tools命名空间的text属性就

  • Android CoordinatorLayout详解及实例代码

    Android CoordinatorLayout详解 一.CoordinatorLayout有什么作用 CoordinatorLayout作为"super-powered FrameLayout"基本实现两个功能: 1.作为顶层布局 2.调度协调子布局 CoordinatorLayout使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果.CoordinatorLayout通过设置子View的 Behaviors来调度子View.系统(Support V7)提供了A

  • Android中ListView Item布局优化技巧

    本文实例讲述了Android中ListView Item布局优化技巧.分享给大家供大家参考,具体如下: 之前一直都不知道ListView有多种布局的优化方法,只能通过隐藏来实现,自己也知道效率肯定是很低的,但是也不知道有什么方法,这些天又查了一些资料,然后知道 其实google早就帮我们想好了优化方案了. 假设你的ListView Item有三种布局样式的可能:就比如很简单的显示一行字,要靠左,居中,靠右. 这时我们就可以在BaseAdapter里面重写两个方法: private static

  • Android 使用CoordinatorLayout实现滚动标题栏效果的实例

    在Material Design里,CoordinatorLayout通常用来作为顶层视图,来协调处理各个子View之间的动作,从而实现各种动画效果,如Snackbar与FloatingActionButton的配合显示效果,就是以CoordinatorLayout作为根布局来实现的 CoordinatorLayout提供Behaviors接口,子View通过实现Behaviors接口来协调和其它View之间的显示效果,可以这么理解: CoordinatorLayout让其子View之间互相知道

  • Android中关于CoordinatorLayout的一些实用布局技巧

    介绍 CoordinatorLayout是一个"加强版"的 FrameLayout,它主要有两个用途: (1) 用作应用的顶层布局管理器 (2) 通过为子View指定 behavior 实现自定义的交互行为. 在我们做 Material Design 风格的app时通常都使用 CoordinatorLayout 作为布局的根节点,以便实现特定的UI交互行为. 那么现在我们来看看如何用已有的一些控件实现一些常见的布局. Toolbar + TabLayout 实现 TabLayout 置

  • Android中Snackbar的使用方法及小技巧

    前言 Snackbar和Toast相似,都是为了给用户提供交互信息,Snackbar是固定在底部的,显示时从下往上滑出 要使用Snackbar,需要在项目的build.gradle中添加依赖 dependencies { compile 'com.android.support:design:23.4.0' } Snackbar的使用方法和Toast很相似 Snackbar.make(mOpenTv, "消息内容", Snackbar.LENGTH_SHORT) .setAction(

  • Vue中$once的两个实用小技巧分享

    目录 前言 清除定时器 $once/$emit + async/await 实现 Dialog 同步执行 总结 前言 在 Vue 中有很多 API 都有很实用的地方,只是需要挖掘适用的场景,这里整理出了 $once 的两个小技巧,也是在平常工作中用的比较多的,分享给大家,希望对大家能有帮助. 清除定时器 定时器大家用的应该也不少,像我一开始一般都是这样写的,在 created 中创建定时器,在 beforeDestroy 中销毁定时器. <script> export default { na

  • android 中使用TableLayout实现表单布局效果示例

    使用TableLayout表格布局实现表单效果 1.核心知识点 android:divider="@drawable/table_v_divider" android:showDividers="middle|beginning|end" 2.样式代码 style样式 <?xml version="1.0" encoding="utf-8"?> <resources> <!--灰色8a8a8a18

  • 实例讲解Android中ViewPager组件的一些进阶使用技巧

    我们经常看到使用了ViewPager的App,在每页上面都会有一个滑块来标志当前处于哪一页.在PagerView包里有android.support.v4.view.PagerTitleStrip和android.support.v4.view.PagerTabStrip两个组件,可以在布局文件中,作为ViewPager的子标签,并设定相对与ViewPager的位置(比如顶部).但这两个组件都很丑,并且标题会随着页面一起滑动,所以一般都不用. 其实实现一个滑块标志当前页面也很简单,大概需要两步:

  • 详解android特性之CoordinatorLayout用法探析实例

    当我在AS上新建一个module时,系统默认的最外层布局不再是我们熟悉的五大布局中的一种,而是一个全新的布局:CoordinatorLayout.它是Material风格的重要组件, 作为布局的顶层控件,协调(Coordinate)其他组件, 实现联动. 下面来看一个最简单的例子,CoordinatorLayout与FloatingActionButton的使用,它可以使浮动按钮上下移动,为Snackbar流出空间来展示. 定义的布局文件如下: <?xml version="1.0&quo

  • Android中协调滚动布局的实现代码

    目录 使用 AppbarLayout 和 MotionLayout 实现常用的布局效果 一.AppbarLayout + ViewPager 二.AppbarLayout + RecyclerView 三.MotionLayout 总结 使用 AppbarLayout 和 MotionLayout 实现常用的布局效果 前文我们讲了协调滚动的一些定义方式,我们在开发中常用的几种效果都可用 AppbarLayout 或 MotionLayout 来实现. 这里先上效果图 可能大家都比较会Appbar

  • Android中的LinearLayout布局

    LinearLayout : 线性布局 在一般情况下,当有很多控件需要在一个界面列出来时,我们就可以使用线性布局(LinearLayout)了,  线性布局是按照垂直方向(vertical)或水平方向(horizontal)的顺序依次排序子元素,每一个子元素都位于前一个元素之后,下面我们就简单的了解一下吧 在XML布局文件中会遇到如下一些单位 px:是屏幕的像素点   dp:一个基于density的抽象单位,屏幕的物理尺寸   sp:同dp相似,但会根据用户的字体大小进行缩放 XML代码如下:改

  • 深入解析Android中的setContentView加载布局原理

    前言 对于Android的开发者来说,setContentView大家再熟悉不过了,在我们的Activity中首先就是要用它加载我们的布局,但是应该有一部分人是不知道加载布局的原理,也包括我,今天就从源码的角度分析setContentView加载布局原理. 准备工作 由于我们使用的Android API部分源码是隐藏的,当我们在AndroidStudio中是不能找到源码的,我们可以去官网下载相应源码去查看,当然在GitHub下载相应版本的API替换我们sdk下platforms相应api的and

随机推荐