MaterialDesign之AppBarLayout与CollapsingToolbarLayout的学习
# 一、简述
本文要介绍的AppBarLayout与CollapsingToolbarLayout均是随MaterialDesign出现的新控件,两者的作用呢,可以说就是为了“增强”Toolbar的吧,它们的出现使得Toolbar不再只是那个木讷的"ActionBar",而是一个真正有灵性,有活力的APP工具条。下面就来看看它们是怎么使用的吧。
# 二、使用
# 1、CoordinatorLayout
在使用AppBarLayout与CollapsingToolbarLayout之前,先来说说这个CoordinatorLayout。CoordinatorLayout直译为“协调布局”,顾名思义,它就是用来协调子布局及控件的,要使用它,则必须把它设置为整个布局的根,同时,通过对“特殊子控件”设置app:appbar_scrolling_view_behavior属性的值,进而来协调子控件在整个布局中的显示位置。本文不对其进行深入讲解,我们这里只需知道,要使用AppbarLayout来“增强”Toolbar,就需要用到CoordinatorLayout即可。CoordinatorLayout的使用示例代码:
<?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.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="256dp">
...
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
从上面的代码中,可以知道,这里只对NestedScrollView控件设置了app:appbar_scrolling_view_behavior属性,没错,NestedScrollView是上面说到的“特殊子控件”,像这样的“特殊子控件”有3个,分别是RecyclerView、ViewPager、NestedScrollView,它们的使用基本是一样的,app:appbar_scrolling_view_behavior属性也只对这3个“特殊子控件”有效。对于这个NestedScrollView,你可以认为,它就是ScrollView的增强版而已。好了,下面就开始介绍本文的主角。
# 2、AppBarLayout
下面是官方文档中对AppBarLayout的描述:
AppBarLayout是一个垂直的LinearLayout,实现了Material Design中app bar的scrolling gestures特性。AppBarLayout的子View应该声明想要具有的“滚动行为”,这可以通过layout_scrollFlags属性或是setScrollFlags()方法来指定。 AppBarLayout只有作为CoordinatorLayout的直接子View时才能正常工作, 为了让AppBarLayout能够知道何时滚动其子View,我们还应该在CoordinatorLayout布局中提供一个可滚动View,我们称之为scrolling view。scrolling view和AppBarLayout之间的关联,通过将scrolling view的Behavior设为AppBarLayout.ScrollingViewBehavior来建立。
结合上面CoordinatorLayout部分中贴出的代码,这段描述的后半段是不难理解的,而比较难理解的应该是layout_scrollFlags属性,描述中的scrolling view就是上面所说的“特殊子控件”。要牢记,描述中说的是对AppbarLayout的直接子控件设置layout_scrollFlags属性,下面来看看都有哪些ayout_scrollFlags属性:
scrollFlags的属性值 | 作用 |
---|---|
scroll | 让AppBarLayout与scrolling view合为一体,当scrolling view滚动时,AppBarLayout也跟着一起滚动。这是“增强”Toolbar的一个必需取值,可以跟其他值一起使用,从而实现不同的“增强”效果。单独使用scroll的话,其效果就类似给ListView加了一个HeaderView。 |
<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.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="CSDN_LQR"
app:layout_scrollFlags="scroll"
app:titleTextColor="@android:color/white"/>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
scrollFlags的属性值 | 作用 |
---|---|
scroll | enterAlways | 当scrolling view向上滚动时,AppBarLayout也跟着一起滚出屏幕,一旦scrolling view向下滚动,AppBarLayout也跟着一起滚入屏幕。 |
<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.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:title="CSDN_LQR"
app:titleTextColor="@android:color/white"/>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
scrollFlags的属性值 | 作用 |
---|---|
scroll | enterAlways | enterAlwaysCollapsed | 当scrolling view向上滚动时,AppBarLayout也跟着一起滚出屏幕,一旦scrolling view向下滚动,AppBarLayout便先慢慢滚动到折叠高度(即最小高度),直到scrolling view向下滚动到最顶部时,AppBarLayout再先慢慢滚动到原来的高度(此时scrolling view也会再次和AppBarLayout一起滚动)。 |
<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.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="150dp"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
app:title="CSDN_LQR"
app:titleTextColor="@android:color/white"/>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
scrollFlags的属性值 | 作用 |
---|---|
scroll | exitUntilCollapsed | 当scrolling view向上滚动时,AppBarLayout也跟着一起滚出屏幕,直到达到了折叠高度(即最小高度),此时AppBarLayout不再滚动,也就是不完全滚出屏幕,而当scrolling view向下滚动到最顶部时,AppBarLayout才会再随scrolling view一起滚动,直到原来的高度。 |
<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.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="150dp"
android:minHeight="?attr/actionBarSize"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title="CSDN_LQR"
app:titleTextColor="@android:color/white"/>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
scrollFlags的属性值 | 作用 |
---|---|
scroll | snap | snap有仓促的意思,效果同它的意思一样,当scrolling view处于无法再向下滚动的状态时(即已经到顶部了),此时向上滚动scrolling view,AppBarLayout将一次全部滚出屏幕,或向下滚动scrolling view,AppBarLayout将一次全部滚入屏幕。有一种引力的感觉。 |
<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.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="150dp"
android:minHeight="?attr/actionBarSize"
app:layout_scrollFlags="scroll|snap"
app:title="CSDN_LQR"
app:titleTextColor="@android:color/white"/>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
好啦,AppBarLayout对Toolbar的“增强”就差不多这样了,不过要纠正一点,其实AppBarLayout并不只是对Toolbar"增强",对于其他控件也是一样的,只是AppBarLayout与Toolbar的搭配比较常见而已。下面接着来看看CollapsingToolbarLayout具体可以对Toolbar做到怎样的“增强”。
# 3、CollapsingToolbarLayout
CollapsingToolbarLayout对Toolbar的“增强”就是把Toolbar变成可折叠的,使其具有更多的交互花样(其实也就是更多的交互动画),我们先来看看可以实现的效果:
要实现上图的效果,需要跟AppBarLayout一起使用,CollapsingToolbarLayout的使用很简单,直接包裹Toolbar即可,其中可以增加一个ImageView控件来作为CollapsingToolbarLayout的“背景”,其实CollapsingToolbarLayout本身是一个FrameLayout,所以其子控件的摆放就是从左上角开始,一个个叠加起来。不过,其中的Toolbar默认一开始是隐藏的。
<?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.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="256dp">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@mipmap/palette"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="CSDN_LQR"
app:titleTextColor="@android:color/white"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
...
</android.support.design.widget.CoordinatorLayout>
这代码中有个细节需要注意一下,你可以发现,代码中不再对Toolbar设置app:layout_scrollFlags属性,而是给CollapsingToolbarLayout控件设置了。这不奇怪,因为上面已经说了,app:layout_scrollFlags属性是对AppBarLayout的直接子控件设置的。先来看看效果怎样:
这是默认的效果,可以看到滚动过程中,ImageView和大标题一起向上或向下滚动,其实这个过程中,只有当CollapsingToolbarLayout折叠时,Toolbar才会显示出来,大标题执行了缩放、位置和透明等动画,而Toolbar执行透明动画,两标题重合或分离,看起来好像就只有一个标题一样。此外,上面的布局代码中是有给Toolbar设置样式的,但并没有起作用。CollapsingToolbarLayout提供了文字样式属性,可以分别对大标题(展开标题)与小标题(折叠标题)的文字样式进行设置。
style.xml中文字样式代码如下:
<!--CollapsingToolbarLayout展开时标题文字样式-->
<style name="ExpandedTitleTextAppearance" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">30sp</item>
<item name="android:textColor">#fff</item>
</style>
<!--CollapsingToolbarLayout折叠时标题文字样式-->
<style name="CollapsedTitleTextAppearance" parent="TextAppearance.AppCompat.Title">
<item name="android:textSize">15sp</item>
<item name="android:textColor">#000</item>
</style>
对CollapsingToolbarLayout分别设置展开标题样式与折叠标题样式
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:collapsedTitleTextAppearance="@style/CollapsedTitleTextAppearance"
app:expandedTitleTextAppearance="@style/ExpandedTitleTextAppearance"
>
...
</android.support.design.widget.CollapsingToolbarLayout>
效果:
这样还不够,如果想在CollapsingToolbarLayout折叠时,背景变为纯色、状态栏也一起变色的话,可以通过如下代码设置:
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:collapsedTitleTextAppearance="@style/CollapsedTitleTextAppearance"
app:expandedTitleTextAppearance="@style/ExpandedTitleTextAppearance"
app:contentScrim="?attr/colorPrimary"
app:statusBarScrim="?attr/colorPrimaryDark"
>
...
</android.support.design.widget.CollapsingToolbarLayout>
其中contentScrim设置的是折叠时,CollapsingToolbarLayout的背景色。statusBarScrim设置的是折叠时,状态栏的颜色,可以达到沉浸式的效果,不过这个属性需要Android 5.0以上才能支持,而且,有的国产机对状态栏做了限制,没办法生效,比如锤子的系统,状态栏一起是半透明色,且该属性无法生效,所以,这个效果需视手机及系统版本而定。来看下效果如何:
呀,马马虎虎,不过还差点,需要给图片“背景”设置视差效果,还有大标题文字底部居中显示。给图片“背景”设置视差效果可以通过设置app:layout_collapseMode属性来完成,这个属性只要是CollapsingToolbarLayout的子控件就有,有三种取值,分别是:none、pin、parallax。其中parallax的效果是在CollapsingToolbarLayout折叠时,此布局(或控件)会有视差折叠效果;pin的效果是在CollapsingToolbarLayout折叠后,此布局(或控件)将固定在顶部。none是默认值,即没有效果,实话说,我感觉pin跟none没什么区别(如果觉得我说的不对,请不吝赐教)。至于标题的位置,可以通过app:collapsedTitleGravity和app:collapsedTitleGravity来配置,用法跟layout_gravity一样,就不说了,贴下代码,随便看下效果。
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:collapsedTitleTextAppearance="@style/CollapsedTitleTextAppearance"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleTextAppearance="@style/ExpandedTitleTextAppearance"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:statusBarScrim="?attr/colorPrimaryDark"
app:collapsedTitleGravity="start"
app:expandedTitleGravity="center_horizontal|bottom" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@mipmap/palette"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="CSDN_LQR"
app:titleTextColor="@android:color/white"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
# 最后附上Demo链接
https://github.com/GitLqr/MaterialDesignDemo (opens new window)
- 01
- Flutter - 轻松搞定炫酷视差(Parallax)效果09-21
- 02
- Flutter - 轻松实现PageView卡片偏移效果09-08
- 03
- Flutter - 升级到3.24后页面还会多次rebuild吗?🧐08-11