说 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>
说 AppbarLayout,如何理解可折叠 Toolbar 的定制的更多相关文章
- Android Toolbar样式定制详解
前言 Marterial Design出来也有一段时间了,为了紧跟Google的设计规范,决定在项目中使用Toolbar.使用了一段时间之后,发现很多时候原始的Toolbar并不能满足项目的要求.为了 ...
- 安卓高级6 玩转AppBarLayout,更酷炫的顶部栏 Toolbar
原文大神地址:http://www.jianshu.com/p/d159f0176576 上一篇文章[<CoordinateLayout的使用如此简单 >]上一篇文章<Coordin ...
- 【知识必备】一文让你搞懂design设计的CoordinatorLayout和AppbarLayout联动,让Design设计更简单~
一.写在前面 其实博主在之前已经对design包的各个控件都做了博文说明,无奈个人觉得理解不够深入,所以有了这篇更加深入的介绍,希望各位看官拍砖~ 二.从是什么开始 1.首先我们得知道Coordina ...
- Android CoordinatorLayout、AppBarLayout、DrawerLayout、NavigationView 的使用及问题小结
这里只对Material Design中这几种组件使用的重要部分以及容易出现问题的地方进行汇总(遇坑请直接看最后常见问题部分),详细用法请自行查阅官方文档 一.CoordinatorLayout 介绍 ...
- ToolbarDemo【Toolbar作为顶部导航栏的简单使用】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 简单记录ToolBar作为导航栏的使用.关键点在于如何在dialogfragment中使用toolbar! Toolbar的图标.标 ...
- Spring SpringMVC myBatis(简称SSM)理解
1对Spring的理解 (1)spring是什么? spring是Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架. (2)spring的作用 (a)spring ...
- JUC之线程间定制化通信
线程通信之定制化 之前文章中写了下Condition的使用,这里我们详细说下其中的用法: 首先使用Condition需要实例化Lock private Lock lock = new Reentran ...
- 安卓高级6 CoordinatorLayout
原作者大神地址:http://blog.csdn.net/huachao1001/article/details/51554608 曾在网上找了一些关于CoordinatorLayout的教程,大部分 ...
- Android学习之基础知识十五 — 最佳UI体验(Material Design实战)
一.前言 长久以来,大多数人都认为Android系统的UI并不美观,至少没有iOS系统的美观.以至于很多IT公司在进行应用界面设计的时候,为了保证双平台的统一性,强制要求Android端的界面风格必须 ...
随机推荐
- Python基础语法复习
1.数据类型 List 列表 函数 append(): 在列表末尾追加. count(): 计算对象在列表中出现的次数. extend():将列表内容添加到列表中. index(): 计算对象在列表中 ...
- 微信小程序 wx.getUserInfo 解密 C# 代码 - 转
public static string DecodeUserInfo(string raw, string signature,string encryptedData, string iv) { ...
- 清除EasyUi combotree下拉树的值
由于测试自带的$(“node”).combotree("clear');问题始终解决不了 最终方法: Hdata是JSON数据源, 在它动态加在成功之后(节点全部显示出来,并且可以选择)再清 ...
- 《Head First 设计模式》例子的C++实现(5 单例模式)
最近在学习设计模式,用的是 <Head First 设计模式>这本书.感觉这本书写的还是很不错的,深入浅出的介绍了各种常用的设计模式.唯一有点不方便的地方是这本书的例子全都是用的 Java ...
- P3830 [SHOI2012]随机树
P3830 [SHOI2012]随机树 链接 分析: 第一问:f[i]表示有i个叶子结点的时候的平均深度,$f[i] = \frac{f[i - 1] + 2 + f[i - 1] * (i - 1) ...
- @Vue/Cli 3 关于 render 空的处理
问题场景 vue-cli 3 在打包部署时候会出现 dist folder not working "Uncaught TypeError: Cannot set property 'ren ...
- BugkuCTF SQL注入1
前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...
- Openstack部署踩坑
第一周: 使用kola部署Openstack,vip_address有问题,双网上也不行,就是部署不了,但all-in-one却可以,可是节点不会加. 第二周: 使用Packstack部署Openst ...
- Linux下"负载均衡+高可用"集群的考虑点 以及 高可用方案说明(Keepalive/Heartbeat)
当下Linux运维技术越来越受到企业的关注和追捧, 在某些企业, 尤其是牵涉到电子商务和电子广告类的网站,通常会要求作负载均衡和高可用的Linux集群方案.那么如何实施Llinux集群架构,才能既有效 ...
- ZJOI2008 生日聚会Party
对于任意连续区间的限制,可以转化为以i结尾的所有区间的限制.这个转换在昨天的后缀自动机题也有用到,因此将其命名为区后变换.稍加分析后,我们记录以i结尾任意区间最大差即可进行DP转移.这个转换同时也创造 ...