欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-11-24 08:00:34
介绍 coordinatorlayout是一个“加强版”的 framelayout,它主要有两个用途: (1) 用作应用的顶层布局管理器 (2) 通过为子vi...

介绍

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

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

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

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

toolbar + tablayout 实现 tablayout 置顶效果

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

Android中关于CoordinatorLayout的一些实用布局技巧
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 的显示效果。

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

在实现布局文件前要赋予当前的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的首页

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

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

Android中关于CoordinatorLayout的一些实用布局技巧
各个页面不同样式

第一步要做的是给 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交互动作。

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