Android新特性:CoordinatorLayout、AppBarLayout和CollapsingToolbarLayout

本人很喜欢Material Design 里面的折叠效果,趁着有时间做个demo,学习下CollapsingToolbarLayout的使用。

先来看下效果:

首先我们来分析下,实现该功能需要做些什么?

 

  • 初始状态下,当界面滑动的时候,首先是顶部的布局慢折叠,折叠到一定高度的时候停止折叠,折叠过程中字体和背景色慢慢发生变化。
  • 当停止折叠后,手势继续向上滑动,底部的滑动控件可以继续向上滑;手势向下滑动的时候,当底部的滑动控件滑到顶的时候,再向下滑动,背景图就会慢慢展开到初始高度。

按照以前的做法,实现第一个功能,我们需要监听滑动滑动事件,然后改变顶部布局、title的相关参数;

实现第二个功能就比较麻烦了,整个滑动过程是连续的,所以我们需要重写父布局的事件传递机制,判断 ACTION_MOVE 事件应该由哪个子View来处理,当底部的滑动控件向下滑动到顶部时,又需要将事件传递到顶部的布局,整个过程处理起来比较麻烦。

 

有没有比较方便的方法实现呢?当然有了,它就是今天我们要介绍的Android的新特性,CoordinatorLayout、AppBarLayout和 CollapsingToolbarLayout 三个组件。

 先看下整体的布局:

<?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"
   tools:context=".widget.CollapsingToolbarActivity">

   <android.support.design.widget.AppBarLayout
      android:id="@+id/app_bar"
      android:layout_width="match_parent"
      android:layout_height="200dp">

      <android.support.design.widget.CollapsingToolbarLayout
         android:id="@+id/collaps_toolbar"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@mipmap/bg_head"
         app:collapsedTitleGravity="center"
         app:collapsedTitleTextAppearance="@style/CollapsTextAppearance"
         app:contentScrim="@color/colorPrimaryDark"
         app:expandedTitleGravity="center"
         app:expandedTitleTextAppearance="@style/ExPandTextAppearance"
         app:layout_scrollFlags="scroll|exitUntilCollapsed"
         app:scrimAnimationDuration="1000"
         app:statusBarScrim="@android:color/black"
         app:title="CollapsToolBar"
         app:titleEnabled="true">

         <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:visibility="visible"
            app:contentInsetLeft="0dp"
            app:contentInsetStart="0dp"
            app:layout_collapseMode="pin">
         </android.support.v7.widget.Toolbar>

         <ImageView
            android:layout_width="wrap_content"
            android:src="@mipmap/icon_arrow_left"
            android:paddingTop="18dp"
            android:paddingLeft="18dp"
            app:layout_collapseMode="pin"
            android:paddingStart="18dp"
            android:layout_height="wrap_content"/>
      </android.support.design.widget.CollapsingToolbarLayout>
   </android.support.design.widget.AppBarLayout>

   <android.support.v7.widget.RecyclerView
      android:id="@+id/recyclerview"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layout_behavior="@string/appbar_scrolling_view_behavior">
   </android.support.v7.widget.RecyclerView>

   <android.support.design.widget.FloatingActionButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginRight="30dp"
      android:src="@mipmap/ic_launcher"
      app:layout_anchor="@id/app_bar"
      app:layout_anchorGravity="right|bottom|end"/>

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

一、CollapsingToolBarLayout 

CollapsingToolBarLayout 提供了一个可折叠的ToolBar布局,主要的属性有:

  • app:title :设置CollapsingToolBarLayout 的title显示的内容,要显示title,必须先设置 app:titleEnabled="true"(默认该属性是false),而且 CollapsingToolBarLayout 的子View中要包含一个ToolBar,否则不会显示出来;
  • app:contentScrim:设置折叠之后 CollapsingToolBarLayout 的背景色;
  • app:collapsedTitleXXX : collapsedTitleXXX 系列属性值用于设置 折叠之后的title 的样式和位置;
  • app:expandedTitleXXX : expandedTitle 系列属性值用于设置 未折叠之前的 title 的样式和位置;
  • app:scrimAnimationDuration:折叠变换动画的执行时间
  • app:statusBarScrim:设置折叠之后 statusBar 的背景色-------------------------还有疑问
  • layout_collapseParallaxMultiplier :不折叠视差系数,配合parallax模式使用,取值有点类似alpha(不透明度),在0.0 ~ 1.0之间,默认值为0.5。当设置为1.0,滚动列表时图片不会折叠移动

以上是 CollapsingToolBarLayout 本身的属性值,从属性的作用我们可以看出 CollapsingToolBarLayout  本身的属性可以完成背景图,title的变化效果的设置。从整体的布局我们看到 CollapsingToolBarLayout  的子布局 ToolBar有个属性

app:layout_collapseMode="pin"

layout_collapseMode 折叠模式,用于指定 CollapsingToolBarLayout 折叠之后该View的行为,有三个值可选:

  • pin : 表示 CollapsingToolBarLayout 折叠之后,该View固定不动
  • none : 默认行为,会随着 CollapsingToolBarLayout 折叠而消失
  • parallax :设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,
    实现视差滚动效果,通常和CollapsingToolBarLayout 的属性 layout_collapseParallaxMultiplier(设置视差因子)搭配使用

 我们可以用该模式来实现折叠之后显示的蓝色背景的ToolBar ,有人可能会问 CollapsingToolbarLayout 布局下为什么还要加一个 ToolBar 控件,用其他布局可以吗?可以的,只不过 CollapsingToolbarLayout  自带的title 要显示出来的有两个条件是必须的:

 

  1.  app:titleEnabled="true"(默认该属性是false)。
  2. CollapsingToolbarLayout 子View要有一个ToolBar。CollapsingToolbarLayout 的 title 在折叠过程中会有移动,大小,颜色等变换效果,最终是移动到 ToolBar上的,所以我们在 CollapsingToolbarLayout 下添加一个 ToolBar。

到这里我们发现 CollapsingToolBarLayout  默认已经具备实现第一个需求的条件了,但是这样设置一定会执行吗?当然。。不是啦,聪明如你,我想已经发现

app:layout_scrollFlags="scroll|exitUntilCollapsed"

这个属性是做什么的?CollapsingToolBarLayout  的自定义属性可没有它呀,那么只有一个可能就是属性来自他的父布局 AppBarLayout

 

二、AppBarLayout 

 layout_scrollFlags 指定 AppBarLayout  的子View 滚动模式,可选值有:

 

  • scroll : 要想滚动必须设置该模式
  • enterAlways :实现quick return效果,向下滑动的时候,快速显示view
  • enterAlwaysCollapsed :当你的View已经设置minHeight属性又使用此标志时,向下滑动到 minHeight 的高度之后,才会开始显示view
  • exitUntilCollapsed :向上滚动时收缩View,但可以固定Toolbar一直在上面
  • snap :子 View不会存在局部显示的情况,滚动子View的部分高度,当我们松开手指时,子View要么向上全部滚出屏幕,要么向下全部滚进屏幕

可以设置多个值,比如:

app:layout_scrollFlags="scroll|exitUntilCollapsed"

这样第一个需求就差不多可以完成了,但是 AppBarLayout  不会自己去滚动呀,要有人来推一把的。这就要认识下第三位兄弟 CoordinatorLayout 了。

 

三、CoordinatorLayout

         协调布局,协调(Coordinate)其他组件, 实现联动的布局。只有最外层是这个布局,一些滚动行为的参数才能使用。比如说:

 

 

   <android.support.v7.widget.RecyclerView
      android:id="@+id/recyclerview"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layout_behavior="@string/appbar_scrolling_view_behavior">

app:layout_behavior 这个属性,这个属性是用来做什么的呢?这个属性就是用来协调各个组件的关键,behavior 就是用来定义一种行为,当带有该属性的组件滚动的时候,各个组件随之作出的行为。就比如说 CollapsingToolBarLayout 收缩,收缩到一定高度的时候RecyclerView继续滚动。我们来看下今天的例子:

看到这里我相信大家都会有疑问:

 

  1. 是不是无论什么控件(或者是可以滑动的控件)设置 layout_behavior 属性,都可以实现这样的效果?换句话说就是什么控件设置 layout_behavior 属性才可以实现联动的效果?
  2. 直接使用 CollapsingToolBarLayout 不行吗,为什么还要套一层AppBarLayout,套其他的布局可以吗?

我们先来看第一个问题,这个问题和 NestedScrolling机制 有关,关于这个机制可以去看下鸿阳大神关于该机制的解析:

Android NestedScrolling机制完全解析 带你玩转嵌套滑动

我们看下 CoordinatorLayout 的实现:

了解过NestedScrolling机制之后,是不是觉得很眼熟,我们再来看下 RecyclerView的实现:

是不是有种恍然大悟的感觉,没错 CoordinatorLayout 协调的原理就是来自NestedScrolling机制,所以 layout_behavior 是设置在实现了 NestedScrollingChild2 接口的滑动控件中,当RecyclerView发生滑动事件时,会将滑动事件交由 CoordinatorLayout 进行统一协调。

 

 

 

我们再来看第二个问题,从第一个问题中我们知道了当 RecyclerView 滑动时 AppBarLayout 会跟着变化,原因在于我们设置的 layout_behavior 的属性值 @string/appbar_scrolling_view_behavior ,我们深入去看下:

<string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>
 

接着到指定的目录下找到 ScrollingViewBehavior 这个类:

 

public static class ScrollingViewBehavior extends HeaderScrollingViewBehavior {

    public ScrollingViewBehavior() {}

    public ScrollingViewBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);

        final TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.ScrollingViewBehavior_Layout);
        setOverlayTop(a.getDimensionPixelSize(
                R.styleable.ScrollingViewBehavior_Layout_behavior_overlapTop, 0));
        a.recycle();
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        // We depend on any AppBarLayouts
        return dependency instanceof AppBarLayout;
    }

只截出部分代码,有兴趣的小伙伴可以去看看源码。了解 NestedScrolling机制的你,一眼就能看出 layoutDependsOn 这个方法做了判断,只处理 AppBarLayout 。因为我们使用了 AppBarLayout 的默认行为 AppBarLayout$ScrollingViewBehavior,所以要套一层 AppBarLayout。我们来看下 ScrollingViewBehavior:

嗯,好像知道了。我们实现 CoordinatorLayout$Behavior 接口,就可以自定义behavior啦。

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值