Android Design Support Library系列之八:AppBarLayout、CollapsingToolbarLayout

使用前添加依赖:

compile 'com.android.support:design:25.3.1'

一、AppBarLayout

官方文档

1、介绍

1)AppBarLayout继承自LinearLayout,是一个垂直的线性布局
2)AppBarLayout内的子View可以通过设置app:layout_scrollFlags=" "属性来决定自己执行何种动作.

使用前提

1)需要使用CoordinatorLayout作为父容器,如果使用其它的ViewGroup,AppBarLayout的大部分功能将无法生效.
2)AppBarLayout同时也需要一个具有单独滚动能力的兄弟节点(实现了NestedScrollingChild接口)才能发挥其功能。

AppBarLayout和其兄弟节点绑定是通过:

AppBarLayout.ScrollingViewBehavior行为类

2、简单使用

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

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/text" />
    </android.support.v4.widget.NestedScrollView>

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

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll"
            app:title="一生所爱"
            app:titleTextColor="#ffffff" />
    </android.support.design.widget.AppBarLayout>

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

效果图:


可以看见,被AppBarLayout包裹的Toolbar在NestedScrollView滚动时跟随着一起滚动,这就是AppBarLayout的作用了。

我们可以通过为AppBarLayout内的子View设置app:layout_scrollFlags=" "属性来决定------当AppBarLayout的兄弟节点滚动状态发生变化时-------AppBarLayout内的子View执行何种动作.

3、app:layout_scrollFlags属性值

(1)scroll--------该View随滚动事件一起发生滚动,就好像RecyclerView滚动时,其Header也一起滚动,没有设置这个flag的子View将被固定在屏幕顶部
注意:
如果使用了下面其它几个值,必定要使用这个值才能起作用;
如果AppBarLayout中某个子View前面的任何其它子View没有设置这个值,那么该View的这条属性将失去作用.

(2)enterAlways--------当兄弟节点往下滚动时,该View会直接往下滚动,而不用考虑兄弟节点是否在滚动,相当于快速返回模式.
和scroll一起使用:app:layout_scrollFlags="scroll|enterAlways"

(3)enterAlwaysCollapsed--------enterAlways的附加选项,一般跟enterAlways一起使用,首先触发enterAlways快速返回效果,但并不会完全快速返回,当View快速返回的高度达到最小高度时,View就暂时不去往下滚动,直到兄弟节点滑动到顶部时,View再继续往下滑动,也就是有保留的快速返回.

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

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="233dp"
            android:minHeight="?android:attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
            app:title="一生所爱"
            app:titleTextColor="#ffffff" />
    </android.support.design.widget.AppBarLayout>


(4)exitUntilCollapsed--------当兄弟节点向上滚动时,该View向上滚动逐渐消失时,会保留一个最小高度,当该View剩下的的高度达到它的最小高度后,不再响应滚动事件,也就是有保留的向上滚动.

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

        <android.support.v7.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="233dp"
            android:minHeight="?android:attr/actionBarSize"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:title="一生所爱"
            app:titleTextColor="#ffffff" />
    </android.support.design.widget.AppBarLayout>

(5)snap--------和scroll一起使用
使用了snap后,该View要么不显示,要么全部显示
【i】当兄弟节点向上滚动,该View消失的高度不足本身一半,松开手指停止滚动后,该View会弹回来,大于一半该View会自动滚动消失
【ii】当兄弟节点向下滚动,该View显示的高度不足本身一半,松开手指停止滚动后,该View会弹回去,大于一半该View会自动滚动显示完全

app:layout_scrollFlags="scroll|snap"

有弹性的快速返回与消失


4、简单介绍实现原理

你肯定会很好奇这种效果是怎么实现的,如果你对CoordinatorLayout以及Behavior有所了解,或者你看过我的另外一篇文章Android Design Support Library系列之七:CoordinatorLayout,你应该知道一些实现细节了。
(1)在AppBarLayout中定义好了2个Behavior:AppBarLayout.BehaviorAppBarLayout.ScrollingViewBehavior
(2)AppBarLayout.Behavior是给AppBarLayout自己使用的,已经通过注解的方式给AppBarLayout使用了:

@CoordinatorLayout.DefaultBehavior(AppBarLayout.Behavior.class)
public class AppBarLayout extends LinearLayout {
  ......
}

在AppBarLayout.Behavior中,AppBarLayout通过NestedScroll一系列方法决定了其兄弟节点滚动状态变化时,AppBarLayout内子View执行何种动作
(3)AppBarLayout.ScrollingViewBehavior是给AppBarLayout兄弟节点使用的,我们一般通过在其兄弟节点上添加下面这条属性使用该Behavior:

app:layout_behavior="@string/appbar_scrolling_view_behavior"

AppBarLayout.ScrollingViewBehavior中:

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

        @Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
                View dependency) {
            offsetChildAsNeeded(parent, child, dependency);
            return false;
        }
  ......
}

其兄弟节点使用了该Behavior后,和AppBarLayout就存在依赖关系了.
(i)这也解释了为什么上面我的NestedScrollView放在AppBarLayout上面,结果效果图中NestedScrollView在AppBarLayout下方,这是因为在依赖关系中:不管child(NestedScrollView)的顺序如何,你的child将总是在所依赖的dependency(AppBarLayout)放置之后才会被放置。
(ii)同时,在AppBarLayout状态发生变化时(位置、大小等),NestedScrollView也会执行相应变化:

offsetChildAsNeeded(parent, child, dependency);

二、CollapsingToolbarLayout

官方文档

1、介绍

1)CollapsingToolbarLayout继承自FrameLayout.
2)CollapsingToolbarLayout通常用来在布局中包裹一个Toolbar,以实现具有“折叠效果“的顶部栏.
3)CollapsingToolbarLayout必须作为AppBarLayout的直接子View使用才能发挥出效果.

2、效果图

3、主要功能

(1)Collapsing title(折叠title):当CollapsingToolbarLayout布局内容全部可见时,title 是最大的,当AppBarLayout 兄弟节点向上滚动,CollapsingToolbarLayout布局内容开始滑出屏幕时,title 将变得越来越小
Tips:
a)为CollapsingToolbarLayout设置title

app:title=" "属性
或者setTitle(CharSequence) 方法

b)当CollapsingToolbarLayout和被其包裹的Toolbar同时设置了app:title=" "属性时,CollapsingToolbarLayout的生效;若CollapsingToolbarLayout没有设置而Toolbar设置了,Toolbar的生效;都没有设置将没有title.

c)设置title大小、颜色等样式

(此处指的是完全扩张时)
app:expandedTitleTextAppearance=" "  设置大小、颜色等样式

也可以通过代码来设置:
setExpandedTitleColor( )  设置颜色
setExpandedTitleTextAppearance( )  设置大小、颜色等样式
(此处指的是折叠到最小时)
app:collapsedTitleTextAppearance=""  设置大小、颜色等样式

setCollapsedTitleTextColor()  设置颜色
setCollapsedTitleTextAppearance()  设置大小、颜色等样式

d)设置title位置

(此处指的是折叠到最小时)
属性:
app:collapsedTitleGravity=" "

代码:
setCollapsedTitleGravity()
(此处指的是完全扩张时)
属性:
app:expandedTitleGravity=" "

代码:
setExpandedTitleGravity()

e)设置CollapsingToolbarLayout完全扩张时的Margin

app:expandedTitleMargin=""
app:expandedTitleMarginTop=""
app:expandedTitleMarginBottom=""
app:expandedTitleMarginStart=""
app:expandedTitleMarginEnd=""

(2)Content scrim(内容纱布):当CollapsingToolbarLayout折叠到一定阈值的时候,为其盖上一层"纱布".

通过 app:contentScrim=" "属性或者setContentScrim(Drawable)方法来设置该“纱布”

Tips:纱布可以是一种颜色,也可以是一张图片

(3)Status bar scrim(状态栏纱布):根据滚动位置是否到达一个阀值决定是否对状态栏盖上一层“纱布”,你可以通过app:statusBarScrim=""属性或者setStatusBarScrim(Drawable)方法来设置该“纱布”.
仅仅在LOLLIPOP设备上面(Android 5.0---API21)起作用.

(4)Parallax scrolling children(有视差地滚动子View):其实就是在视觉上比CollapsingToolbarLayout中其它子View滚动的慢一点

app:layout_collapseMode="parallax " 用在被CollapsingToolbarLayout包裹的子View上
然后用:
app:layout_collapseParallaxMultiplier=" "控制视差系数
或者 通过setParallaxMultiplier(float)控制视差系数

(5)Pinned position children(固定子View位置 ):子View可以选择是否在全局空间上固定位置,这对于Toolbar来说非常有用,因为当布局在移动时,可以将Toolbar固定位置而不受移动的影响

在被CollapsingToolbarLayout包裹的子View上设置:
    app:layout_collapseMode="pin" 

4、代码

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

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/text" />
    </android.support.v4.widget.NestedScrollView>

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

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"

            app:title="一生所爱"
            app:collapsedTitleGravity="center"
            app:collapsedTitleTextAppearance="@style/MyCollapsedTitleStyle"
            app:expandedTitleGravity="right|bottom"
            app:expandedTitleTextAppearance="@style/MyExpandedTitleStyle"
            app:contentScrim="@android:color/holo_blue_dark" >

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="233dp"
                android:scaleType="centerCrop"
                android:src="@mipmap/zy"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7">
            </ImageView>

            <android.support.v7.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="?android:attr/actionBarSize"
                app:layout_collapseMode="pin" />
        </android.support.design.widget.CollapsingToolbarLayout>

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

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

styles.xml中:

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>

        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="MyExpandedTitleStyle" parent="TextAppearance.Design.CollapsingToolbar.Expanded">
        <item name="android:textSize">25sp</item>
        <item name="android:textColor">@android:color/holo_purple</item>
    </style>

    <style name="MyCollapsedTitleStyle">
        <item name="android:textSize">16sp</item>
        <item name="android:textColor">@android:color/white</item>
    </style>
</resources>

三、小结

使用AppBarLayout、CollapsingToolbarLayout可以实现很多酷炫的效果,你还在等什么,还不去尝试一下!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容