说 AppbarLayout,如何理解可折叠 Toolbar 的定制

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

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

本文的目的就是详细地介绍怎么样通过 AppBarLayout 与 CoordinatorLayout 的配合使用,去定制一个可折叠的 Toolbar。然后继续通过 CollapsingToolbarLayout 进一步增强 Toolbar 的视觉效果。如果有人对可折叠的的 Toolbar 还不了解,那么请看下面的示例。
这里写图片描述

本文涉及的内容主要有 AppBarLayout 与 CollapsingToolbarLayout 的属性与 API 的细节。

内容较多,下面,开始一一道来。

CoordinatorLayout、AppBarLayout、Toolbar 之间的关系

有同学可能不是太了解 CoordinatorLayout 这个类,其实没有太大的关系,下面我会简单介绍一下它的大致功能。

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

所以,CoordinatorLayout 编程的关键是它的子 View 们配置的 Behavior.

AppBarLayout 本身有默认的 Behavior,这使得它能够响应依赖对象的位置变化或者是 CoordinatorLayout 中产生的嵌套滑动事件,这从它的源码中可以看出来。

@CoordinatorLayout.DefaultBehavior(AppBarLayout.Behavior.class)
public class AppBarLayout extends LinearLayout {
AppBarLayout 对象默认配置了一个 Behavior。而正是这个 Behavior,它会响应外部的嵌套滑动事件,然后根据特定的规则去伸缩和滑动内部的子 View。本文的主要目的就是要讲解这些特定的规则及它们作用后的效果。

AppBarLayout 本身想提供一个 AppBar 的概念,所以严格地讲它本身与 Toolbar 没有直接的关系。AppBarLayout 内部的子 View 不一定非要是 Toolbar,它可以是任何 View,比如,你可以放置进去一张图片、一个列表、一个 ViewPager 等等。
我们知道,Android 的历史进程中,大概有 TitleBar、ActionBar、Toolbar 的进化,这是 Android 设计语言的改良过程。而后来随着 Material Design 设计的出现,它又提供了 AppBar 的概念,而 AppBarLayout 则是 AppBar 在 Android 中的代码实现。
这里写图片描述

AppBarLayout 虽然和 Toolbar 没有直接联系,但是当 Toolbar 内置在 AppbarLayout 中的时候,Toolbar 的效果增强了,这使得开发者非常愿意用 AppBarLayout 与 Toolbar 配合使用,这比单独使用 Toolbar 炫丽的多。所以,基本上有 AppBarLayout 的地方就有 Toolbar。通过 AppBarLayout 实现一个可伸缩折叠的 Toolbar 也是本文的目的。

当我们运用 support design 中的组件时,我们应该拥有下面几个最基本的意识:

1. CoordinatorLayout 是这个库的组织容器,一切基于 support design 扩展出来的特性都应该发生在 CoordinatorLayout 及它的子 View 体系中。

2. AppbarLayout 应该作为一个 CoordinatorLayout 的直接子 View,否则它与普通的 LinearLayout 无异。

3. AppbarLayout 的子 View 不仅仅是 Toolbar,它们可以是任何的 View,但通常和 Toolbar 配合使用。

AppBarLayout 基本使用方法

AppBarLayout 是 android support design 这个支持包中的类,前面说过它的一切效果都建立在 CoordinatorLayout 这个父类容器之上,AppBarLayout 要想正常发挥它的所有特性,那么它必须作为 CoordinatorLayout 的直接子类。

引入依赖

android support design 没有内置在 SDK 中,所以我们需要引入依赖。

compile 'com.android.support:design:25.0.1'
1
1
与嵌套滑动组件配合

在 AppBarLayout 官方文档注释中有这么一段。

AppBarLayout 需要和一个独立的兄弟 View 配合使用,这个兄弟 View 是一个嵌套滑动组件,只有这样 AppBarLayout 才能知道什么时候开始滑动。它们之间关系的绑定通过给嵌套滑动的组件设立特定的 Behavior,那就是 AppBarLayout.ScrollingViewBehavior。
然后,官方还给出了示例。

<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.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<!-- Your scrolling content -->

</android.support.v4.widget.NestedScrollView>

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

<android.support.v7.widget.Toolbar
...
app:layout_scrollFlags="scroll|enterAlways"/>

<android.support.design.widget.TabLayout
...
app:layout_scrollFlags="scroll|enterAlways"/>

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

</android.support.design.widget.CoordinatorLayout>
上面布局文件中,NestedScrollView 就是那个配套的滑动组件,它需要和 AppBarLayout 进行绑定,所以它必须指定 Behavior。在 xml 中通过

app:layout_behavior="@string/appbar_scrolling_view_behavior"
1
1
多说两句,有同学可能会想一定要是 NestedScrollView 吗?

当然不是,在 CoordinatorLayout 中嵌套滑动的本质是一个 NestedScrollingChild 对象。

NestedScrollingChild 是一个接口,目前它的实现类有 4 个。
这里写图片描述

所以除了使用 NestedScrollView,我们还经常使用 RecyclerView 和 SwipeRefreshLayout 作为配套的嵌套滑动组件,这是其它博文都没有提到的,希望大家注意。

可能大家注意到了上面示例中有 app:layout_scrollFlags 这样的属性,大家一定很好奇,它们是如何作用的。不要着急,下面就讲这一块的内容。

layout_scrollFlags 滑动效果的配置

AppBarLayout 本身也是一个垂直方向的 LinearLayout,所以它的滑动主要是针对内部子 View 的滑动。这就需要设立一种规则来定义滑动的行为。

这个规则就是 AppBarLayout 中内部的子 View 需要在 xml 中配置 layout_scrollFlags。
layout_scrollFlags 取值有 5 个。

scroll
enterAlways
enterAlwaysCollapsed
exitUntilCollapsed
snap
说实话,这 5 个值并不复杂,但是因为命名的关系,它们有点难以理解,很多人应该就是在这一位置卡壳了很久。因为其它的博文都是直接讲 5 个值的用法,然后再配置上动图来解释说明。而对于我而言,这种方式有值得改进的地方,我更愿意先解释目的再解释手段。

我们提炼几个关键字。

它们分别是滑动、折叠、进入、离开、snap。

滑动 scroll

滑动是基础,后面的几个属性都是建立在此属性上的。滑动大家应该很好理解,只有在 AppBarLayout 中的子 View 配置了 scroll 属性,这个 AppBarLayout 都会响应。

<?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:fitsSystemWindows="true"
tools:context="com.frank.supportdesigndemo.appbarlayout.AppbarLayoutActivity">

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
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"
app:layout_scrollFlags="scroll" www.7881188.cn/ />
</android.support.design.widget.AppBarLayout>

<android.support.v4.widget.NestedScrollView
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/large_text">www.huazongyule.net</TextView>
</android.support.v4.widget.NestedScrollView>
我们可以看看动画
这里写图片描述

scroll 这个 layout_scrollFlags 使得 Toolbar 像是 NestedScrollView 本身的一部分一样,它们同步响应滑动。

向上滑动的时候,Toolbar 先滑动,然后 NestedScrollView 中的内容再滑动。

向下滑动的时候,NestedScrollView 中的内容先滑动,然后 Toolbar 再一起滑动。

enter 和 exit 的概念

这两个直译为中文就是进入和离开。这里的主语是 AppBarLayout 中的内容,宾语是 CoordinatorLayout。
这里写图片描述
当 AppBarLayout 中的内容要从 CoordinatorLayout 外面进入内部时,我们用 enter 指代这种行为,对应的手势就是向下滑动。

当 AppBarLayout 中的内容从 CoordinatorLayout 内部向外部方向移动时,我们用 exit 指代这种行为,对应的手势是向上滑动。

collapsed 折叠的概念

其实我更愿意用伸缩解释这个概念。
这里写图片描述

红框部分标明不能再被压缩的范围,其它部分都可以在滑动的过程中伸缩。

collapsed 的高度由相应的 View 的 minHeight 属性指定,也就是一个 View 的最小高度。

与 collapsed 相关的 layout_scrollFlags 有两个:exitUntilCollapsed 和 enterAlwaysCollapsed。

下面一一讲解。

exitUntilCollapsed

前面讲过

当 AppBarLayout 中的内容从 CoordinatorLayout 内部向外部方向移动时,我们用 exit 指代这种行为,对应的手势是向上滑动。
exit 指得是向上滑动的手势动作,但是 exitUntilCollapsed 代表什么呢?
我们再看这张图。
这里写图片描述

黄色部分是可以被压缩的,而红色部分是不能再被压缩的地方。

exitUntilCollapsed 表示的是,向上滑动时,AppBarLayout 中设置了该属性的 View 可以滑动,等到这个 View 可视范围被压缩到 collapsed 指定的高度也就是 minHeight 时,这个 View 不再滑动。

如果还没有理解,那就结合下面的实例效果。

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_ www.aomenyonli.cn layout"
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="250dp"
android:minHeight="www.zbcppt.com 100dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed" />
</android.support.design.widget.AppBarLayout>

运行效果如下:
这里写图片描述

仔细想一想,其实 scroll 和 exitUntilCollapsed 也没有什么太大的区别。

区别在于 exitUntilCollapsed 的存在,让 scroll 滑动受到了一定的限制。这个限制就是 scoll 不再能够进行完全的滑动,因为 collapsed 距离的存在。

enterAlways

enterAlways 也需要和 scroll 配合使用。

我们回到前面仔细观察单独 scroll 标志起作用的动图。

可以发现,这个 scorll 标志起作用的时候,enter 行为发生时,是 NestedScrollView 内容先滑动,然后才是 Toolbar 开始滑动。

而 enterAlways 这个标志与 scroll 配合使用可以改变这种行为,enterAlways 起作用时,当手指向下滑动时,Toolbar 会和 NestedScrollView 一起滑动,它们是同时滑动的。

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
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"
app:layout_scrollFlags="scroll|enterAlways" />
</android.support.design.widget.www.wmyl11.com AppBarLayout>
示例效果:
这里写图片描述

enterAlwaysCollapsed

enterAlways 是增强 scroll 动作的,而 enterAlwaysCollapsed 的目的是进一步细化 enterAlways 的行为的。

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
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="250dp"
android:minHeight="100dp"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed" />
</android.support.design.widget.AppBarLayout>
示例效果如下:
这里写图片描述

大家仔细观察一下,enterAlwaysCollapsed 其实也只是 enter 行为,也就是内容下滑的时候。当它 exit 的时候,也就是说手指向上滑动,它和 scroll 保持一致。

关键是 enter 的时候。

因为有 enterAlways 的存在,Toolbar 会和 NestedScrollView 一起响应滑动,但是又因为 enterAlwaysCollapsed 的存在,它的这种行为被限定了。Toolbar 先滑动,等到视图可见范围高度为 collapsed 指定高度时它会静止,等到 NestedScrollView 内容完全显示在 Toolbar 下方时它再一起滑动,它的动作是 3 段式的。

snap

我不知道该怎么翻译这个词,它其实代表了一种场景,要么让你滑动过去要么滑动失败。大家可以参考下 ViewPager 是怎么滑动的,只不过 ViewPager 是水平方向上的,AppBarLayout 中的内容是垂直方向上的行为。

也就是说 snap 代表一种吸附的行为,当一个滑动事件结束后,Toolbar 会向最接近它的边缘自行滚动。那什么是最近的概念呢?比如向上滑动时,如果滑过了一半它就向上滚动,否则滚动回原来的地方。

用示例来说明

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
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="250dp"
android:minHeight="100dp"
app:layout_scrollFlags="scroll www.wmyl11.com|snap" />
</android.support.design.widget.AppBarLayout>
这里写图片描述

layout_scrollFlags 之间的配合使用

我们前面分析过按照滑动方向,可以分为 enter 和 exit 两种。
而按照每个方向上的行为类别划分,又有不同的行为。
这里写图片描述

其它行为可以自由搭配,比如定制一个 enter 时 enterAlwaysCollapsed,exit 时 exitUntilCollapsed 的行为。

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
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="250dp"
android:minHeight="100dp"
app:layout_scrollFlags="scroll www.baqist.cn/|enterAlways|enterAlwaysCollapsed|exitUntilCollapsed" />
</android.support.design.widget.AppBarLayout>
这里写图片描述

按道理说,因为有 AppBarLayout 的存在,Toolbar 已经多姿多彩了,我们可以利用它们的特性实现很漂亮的 Appbar。

但是,人们仍然不满足,人们希望 Toolbar 的效果能够更加炫丽一些,于是 CollapsingToolbarLayout 这个类出现了。

CollapsingToolbarLayout 的使用

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

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

Collapsing Title 可折叠的标题
Content Scrim 内容纱布
Status bar scrim 状态栏纱布
Parallax scrolling children 子 View 的视差滚动行为
Pinned position children 子类的位置固定行为
下面一一为这些内容讲解。

Collapsing title 可折叠的标题

我们新建一个 Activity,简单试验一下,Collapsing Title 是怎么样一个概念。

<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. www.linlenyl.cn/ android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.frank.supportdesigndemo.appbarlayout.CollapsingActivity">

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

<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<android.support.v7.widget.Toolbar
android:id="@+id/ www.yszx11.cn toolbar"
app:title="title"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/large_text"></TextView>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

这里写图片描述

可以看到,Collapsing title 的概念其实就是 Title 在大小与位置会变化。
我们再做少许变动。

<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="www.lieqibiji.com/ match_parent"
android:layout_height="match_parent"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
app:title="title"
android:backgroundTint="#f00"
android:layout_width="match_parent"
android:layout_ www.yongshiyule178.com/ =" www.6788878.cn/ ?attr/actionBarSize"
android:background="?attr/colorPrimary"
/>
</android.support.design.widget.CollapsingToolbarLayout>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值