一、概述

Android 的历史进程中,大概有 TitleBar、ActionBar、Toolbar 的进化,这是 Android 设计语言的改良过程。而后来随着 Material Design 设计的出现,它又提供了 AppBar 的概念,而 AppBarLayout 则是 AppBar 在 Android 中的代码实现。
对于Toolbar不了解的同学,请参照我的上一篇博客
https://mp.csdn.net/postedit/88931587
引用下别人的图:
Android折叠Toolbar_第1张图片

1.1 什么是 Material Design

谷歌于2014年的 Google I/O 大会上首次亮相推出了全新的 设计语言 Material Design。谷歌表示,这种设计语言旨在为手机、平板电脑、台式机和"其他平台"提供更一致、更广泛的"外观和感觉"。

1.2 关于Material Design

Material Design的出现使得 Android 也能定制高颜值的界面,并且指导了如何实现复杂炫丽的交互效果,而 Android Surpport Desgin 这个支持包就是 Android 官方对 Material Design 的代码实现。

Android Support Desgin 这个包中提供了一系列的组件如:CoordinatorLayout、AppBarLayout、FloatingActionButton 等等。其中 CoordinatorLayout 是核心,它是包内其它组件能够正常工作的前提。

本文的目的就是详细地介绍怎么样通过 AppBarLayout 与 CoordinatorLayout 的配合使用,去定制一个可折叠的 Toolbar。然后继续通过 CollapsingToolbarLayout 进一步增强 Toolbar 的视觉效果。

先看下效果,有兴趣再慢慢学习!
高流量预警,本篇博客插入了大量的图片,建议WIFI下打开!

二、什么是CoordinatorLayout、AppBarLayout、CollapsingToolbarLayout ?

官方给出的使用示例

                                                

Android折叠Toolbar_第2张图片

CoordinatorLayout

CoordinatorLayout是一个“加强版”的 FrameLayout,它主要有两个用途:
(1) 用作应用的顶层布局管理器;
(2) 通过为子View指定 behavior 实现自定义的交互行为。
重点:在我们做 Material Design 风格的app时通常都使用 CoordinatorLayout 作为布局的根节点,以便实现特定的UI交互行为。

AppBarLayout

(1)AppBarLayout 继承自LinearLayout,子控件默认为竖直方向显示,可以用它实现Material Design 的Toolbar;
(2)它支持滑动手势;它的子控件可以通过在代码里调用setScrollFlags(int)或者在XML里app:layout_scrollFlags来设置它的滑动手势。这里的滑动手势可以理解为:当某个可滚动View(如NestedScrollView)的滚动手势发生变化时,AppBarLayout内部的子View(如Toolbar)实现某种动作。
注意:
①实现这些的前提是它的根布局必须是 CoordinatorLayout。
​②AppBarLayout的子控件不仅仅可以设置为Toolbar,也可以包含其他的View。

CollapsingToolbarLayout

CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承自FrameLayout,给它设置layout_scrollFlags,它可以控制包含在CollapsingToolbarLayout中的控件(如:ImageView、Toolbar)在响应layout_behavior事件时作出相应的scrollFlags滚动事件(移除屏幕或固定在屏幕顶端等)。
注意:CollapsingToolbarLayout继承自FrameLayout!
CollapsingToolbarLayout继承自FrameLayout!
CollapsingToolbarLayout继承自FrameLayout!

在 Android 为实现 Material Design 提供的支持包 android support design 中,CoordinatorLayout 毫无疑问是最核心的,它通过子 View 对象配置的 Behavior,实现了子 View 与 CoordinatorLayout、子 View 与子 View 之间一系列复杂的交互。

所以CoordinatorLayout作为一个顶层布局管理器存在。

AppBarLayout 需要和一个独立的兄弟 View 配合使用,这个兄弟 View 是一个嵌套滑动组件,只有这样 AppBarLayout 才能知道什么时候开始滑动。它们之间关系的绑定通过给嵌套滑动的组件设立特定的 Behavior,那就是 AppBarLayout.ScrollingViewBehavior。
NestedScrollView 就是那个配套的滑动组件,它需要和 AppBarLayout 进行绑定,所以它必须指定 Behavior。在 xml 中通过

app:layout_behavior="@string/appbar_scrolling_view_behavior"

嵌套滑动的组件一定要是 NestedScrollView 吗?

当然不是,在 CoordinatorLayout 中嵌套滑动的本质是一个 NestedScrollingChild 对象。 NestedScrollingChild 是一个接口,目前它的实现类有 4 个。
除了使用 NestedScrollView,我们还经常使用 RecyclerView 和 SwipeRefreshLayout 作为配套的嵌套滑动组件。
Android折叠Toolbar_第3张图片

懂的了这些之后,通过给AppBarLayout添加layout_scrollFlags就可以实现滑动效果啦!
下面将详细讲述什么是layout_scrollFlags:
先上代码

<?xml version="1.0" encoding="utf-8"?>                                    

layout_scrollFlags

layout_scrollFlags 取值有 5 个,上面说过,AppBarLayout的子控件可以通过在代码里调用setScrollFlags(int)或者在XML里app:layout_scrollFlags来设置它的滑动手势。可以看出,这里我们的子控件就是Toolbar。

1.scroll
2.enterAlways
3.enterAlwaysCollapsed
4.exitUntilCollapsed
5.snap

scroll(滑动)


scroll(滑动)是基础,后面的几个属性都是建立在此属性上的。只有在 AppBarLayout 中的子 View 配置了 scroll 属性,这个 AppBarLayout 才会响应。

运行:app:layout_scrollFlags=“scroll”
结果:Toolbar和NestedScrollView 同步响应滑动,Toolbar像是NestedScrollView的一部分。

enterAlways、enterAlwaysCollapsed、exitUntilCollapsed

enterAlways 注意看文字的变化

运行:app:layout_scrollFlags=“scroll|enterAlways”
结果:该方法向下滑动时,Toolbar先滑动进入视野,直到Toolbar全部显示后才显示NestedScrollView。

enterAlwaysCollapsed
修改下layout_height=“250dp”,minHeight=“100dp”(只是为了演示效果做的修改)

运行:app:layout_scrollFlags=“scroll|enterAlways|enterAlwaysCollapsed”
结果:该方法向下滑动时,Toolbar先滑动进入视野,因为多了Collapsed(折叠),限制了Toolbar的行为。也就是Toolbar不会完全显示出来才滑动NestedScrollView,而是会先显示一部分。默认先显示一个Toolbar的高度。我们可以通过android:minHeight指定默认显示的高度(这里我们已经设置了minHeight=“100dp”)。当默认高度(100dp)显示出来后,再滑动NestedScrollView,当NestedScrollView显示完成后,继续显示Toolbar剩余部分。
也就是向下滑动分3步进行:
1)先滑动指定的Toolbar的高度,通过minHeight设置
2)滑动NestedScrollView直至顶部
3)滑动剩余的Toolbar的高度

exitUntilCollapsed

运行:app:layout_scrollFlags=“scroll|exitUntilCollapsed”
结果:和上面的enterAlwaysCollapsed类似(先向下滑动到指定高度再滑动NestedScrollView再滑动剩余部分),exitUntilCollapsed是先向上滑动到指定高度再滑动NestedScrollView,区别是剩余部分(minHeight)不滑动。

可以看出来,scroll 和 exitUntilCollapsed 其实没有什么太大的区别。
区别在于 exitUntilCollapsed 的存在,让 scroll 滑动受到了一定的限制。这个限制就是 scoll 不再能够进行完全的滑动,因为 collapsed 距离的存在。

我这里总结下自己对enter和exit的理解(可能不正确,只是方便理解):把Toolbar当成操作对象
enter:【Toolbar】进入【视野】。向下滑动(只对向下滑动各个组件是怎么显示的做限制,向上滑动时就像一个整体同步响应滑动)
exit:【Toolbar】离开【视野】。向上滑动(只对向上滑动各个组件是怎么显示的做限制,向下滑动时就像一个整体同步响应滑动)

①当使用enter时,即进入,Toolbar先进入视野,然后再是NestedScrollView。对离开没有进行操作,故和scroll一样。
②当使用exit时,即离开。Toolbar先离开视野,然后再是NestedScrollView滑动。对进入没有进行操作,故和scroll一样。

snap

表示一种吸附效果。说白点就是如果向下滑动不到Toolbar的一半,Toolbar就不会完全显示,向上滑动不到Toolbar的一半,Toolbar就不会完全收缩。

按道理说,因为有 AppBarLayout 的存在,Toolbar 已经多姿多彩了,我们可以利用它们的特性实现很漂亮的 Appbar。
但是,人们仍然不满足,人们希望 Toolbar 的效果能够更加炫丽一些,于是 CollapsingToolbarLayout 这个类出现了。

CollapsingToolbarLayout

刚刚说过,CollapsingToolbarLayout 出现的目的只是为了增强 Toolbar。

它为 Toolbar 带来了下面几个特性。

1.Collapsing Title 可折叠的标题
2.Content Scrim 内容纱布
3.Statusbar Scrim 状态栏纱布
4.Parallax scrolling children 子 View 的视差滚动行为
5.Pinned position children 子类的位置固定行为

代码体现如下:
Android折叠Toolbar_第4张图片
经过测试:这里设置minHeight无效,那Collapsed怎么发挥效果呢?内部已经规定好了吧。不懂…

分别解释下:

Collapsing Title(可折叠的标题)

注意:这里的title是CollapsingToolbarLayout的title,如果Toolbar也有title,显示的是CollapsingToolbarLayout的。两者都会位置和大小会随着状态改变。

Content Scrim(内容纱布)

内容纱布其实就是为了更好地反馈CollapsingToolbarLayout 中折叠状态的变化。可以将这个变化指定为某种颜色的改变或者图片,它就像是一块纱布一样遮住 title 下面的内容,所以被称为内容纱布。
注意:我说的是 Content scrim 会遮住 title 下方的内容部分。如果一个 CollapsingToolbarLayout 中只有 Toolbar 的话,那么它就不起作用。CollapsingToolbarLayout 本质上是一个 FrameLayout,所以需要在 Toolbar 的前面位置加入其它的 View 作为内容,Content scrim 才会起作用。

Statusbar Scrim(状态栏纱布)

和Content Scrim类似,不过这次作用的对象是statusBar。
注意!注意!注意!
修改状态栏状态(statusBarColor)是在Android 5.0之后才有的特性,也就是最低为API21。设置一下就可以了,因为现在基本创建Android基本都是Android 6.0以上了。

①AppBarLayout要设置android:fitsSystemWindows=“true”
②statusBarColor的颜色要是设置为全透明(transparent)。

@android:color/transparent

或者半透明(没测试过)

 true
Parallax scrolling children 子 View 的视差滚动行为

CollapsingToolbarLayout 可以控制的子 View 滚动模式有 3 种:
1.none------默认,无任何效果
2.Parallax------视差滚动
3.pin------固定某个 View
它通过 xml 属性 app:layout_collapseMode 来设置。需要注意的是,这个属性作用对象是 CollapsingToolbarLayout 中的子 View 并不是 CollapsingToolbarLayout。

如何理解视差?

就是滚动的速度不同,造成的视觉差异效果。也就是说 CollapsingToolbarLayout 中有的 view 滚动的快一些,其它的滚动的慢一些。
它滚动的快慢受 Parallax multiplier 这个因子的影响,默认值为DEFAULT_PARALLAX_MULTIPLIER。也就是 0.5f。也就是正常速度的一半。

Pinned position children 子类的位置固定行为

将 CollapsingToolbarLayout 中某个子 View 固定,无论是否存在滚动事件,只要设置 app:layout_collapseMode=”pin”,视图都不会移动。

回头看,为什么要设置fitsSystemWindows="true"呢?

因为fitsSystemWindows属性可以让view根据系统窗口来调整自己的布局;简单点说就是我们在设置应用布局时是否考虑系统窗口布局,这里系统窗口包括系统状态栏、导航栏、输入法等,包括一些手机系统带有的底部虚拟按键。下面给出图片直观点
当设置了透明状态栏(StatusBar)和透明导航栏(NavigationBar)时,引用下别人的图
Android折叠Toolbar_第5张图片
可以看到,我们的状态栏(StatusBar)或导航栏(NavigationBar)就会变成透明,并且布局会扩展到StatusBar或NavigationBar的位置。
当设置了fitSystemWindows=“true”之后
Android折叠Toolbar_第6张图片

如果想监听 AppBarLayout 中的滑动位移信息,那么添加相应的监听器就好了。

OnOffsetChangedListener

这是 AppBarLayout 定义的监听器。Android折叠Toolbar_第7张图片

verticalOffset 是 AppBarLayout 相对于完全展开时没有滑动的距离。它在初始位置为 0,其它时候都为负数。它绝对值的最大值为 AppBarLayout 的 TotalScollRange。
明白了这个之后,就可以根据 verticalOffset 做透明度动画等丰富的效果了。

更多相关文章

  1. Android 5.0 MaterialDesign Ripple效果水波纹效果
  2. Android用户界面 UI组件--TextView及其子类(一) TextView
  3. android手势操作滑动效果触摸屏事件处理
  4. Android基本组件TextView和EditView
  5. Android中利用GridView实现水平和垂直均有滚动条的表格效果
  6. Android之——史上最简单最酷炫的3D图片浏览效果的实现
  7. Android彻底组件化—如何使用Arouter

随机推荐

  1. golang用什么开发工具?
  2. 详解 Go 语言中的方法
  3. 教你导入golang.org的包
  4. golang是多线程模式吗?
  5. Go如何使用websocket实现弹幕功能
  6. golang是单进程的吗?
  7. golang如何释放map内存?
  8. 代码详解使用Go基于WebSocket构建视频直
  9. golang如何处理输入?
  10. PHP语法和Go语法有什么差异?对比介绍