AppbarLayout是Material Design的一个控件。它继承自LinearLayout,布局方向为垂直方向。所以你可以把它当成垂直布局的LinearLayout来使用。AppBarLayout是在LinearLayou上加了一些材料设计的概念,它可以让你定制当某个可滚动View的滚动手势发生变化时,其内部的子View实现何种动作。
请注意:上面提到的某个可滚动View,可以理解为某个ScrollView。怎么理解上面的话呢?就是说,当某个ScrollView发生滚动时,你可以定制你的“顶部栏”应该执行哪些动作(如跟着一起滚动、保持不动等等)。那某个可移动的View到底是哪个可移动的View呢?这是由你自己指定的!如何指定,我们后面说。
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/tb_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/design_default_color_primary_dark" />
</com.google.android.material.appbar.AppBarLayout>
内部的子View通过在布局中加app:layout_scrollFlags设置执行的动作,那么app:layout_scrollFlags可以设置哪些动作呢?分别如下:
Scroll Flag | 作用 |
---|---|
scroll | 子View如果设置layout_scrollFlags属性的值为scroll,这个View会随着Scrolling View一起滚动,当向上滚动的时候,Toolbar会滚出屏幕外,如果不设置,那么Toolbar会固定不动。 |
enterAlways | 使用这个flag,当Scrolling View 向下滑动时,子View 将直接向下滑动,而不管Scrolling View 是否在滑动。注意:要与scroll 搭配使用,否则是不能滑动的。(上图演示的效果,正是scroll和enterAlways两个flag同时使用产生的效果,即向上滚动,Toolbar滚出屏幕,向下滚动,Toolbar重新进入屏幕)。 |
enterAlwaysCollapsed | enterAlwaysCollapsed 是对enterAlways 的补充,当Scrolling View 向下滑动的时候,滑动View(也就是设置了enterAlwaysCollapsed 的View)下滑至折叠的高度,当Scrolling View 到达滑动范围的结束值的时候,滑动View剩下的部分开始滑动。这个折叠的高度是通过View的minimum height (最小高度)指定的。(要配合scroll|enterAlways 一起使用) |
exitUntilCollapsed | 当Scrolling View 滑出屏幕时(也就时向上滑动时),滑动View先响应滑动事件,滑动至折叠高度,也就是通过minimum height 设置的最小高度后,就固定不动了,再把滑动事件交给 Scrolling view 继续滑动。 |
snap | 在滚动结束后,如果view只是部分可见,它将滑动到最近的边界。比如,如果view的底部只有25%可见,它将滚动离开屏幕,而如果底部有75%可见,它将滚动到完全显示。 |
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。
当我们运用support design中的组件时,我们应该拥有下面几个最基本的意识:
- CoordinatorLayout是这个库的组织容器,一切基于support design扩展出来的特性都应该发生在CoordinatorLayout及它的子View体系中。它的一切效果都建立在CoordinatorLayout这个父类容器之上,AppBarLayout要想正常发挥它的所有特性,那么它必须作为CoordinatorLayout的直接子类,否则它与普通的LinearLayout无异。
- 为了让AppBarLayout能够知道何时滚动其子View,我们还应该在CoordinatorLayout布局中提供一个可滚动View,我们称之为Scrolling View。Scrolling View和AppBarLayout之间的关联,通过将 Scrolling View的Behavior设为AppBarLayout.ScrollingViewBehavior来建立。
AppBarLayout本身有默认的Behavior,这使得它能够响应依赖对象的位置变化或者是CoordinatorLayout中产生的嵌套滑动事件,这从它的源码中可以看出来:
public class AppBarLayout extends LinearLayout implements CoordinatorLayout.AttachedBehavior {
AppBarLayout对象实现了一个Behavior。而正是这个Behavior,它会响应外部的嵌套滑动事件,然后根据特定的规则去伸缩和滑动内部的子View。
下面分别加入AppbarLayout和NestedScrollView作子view,给NestedScrollView加上behavior,就可以让AppbarLayout跟随NestedScrollView的Behavior联动。Android已经自带了app:layout_behavior="@string/appbar_scrolling_view_behavior",只要滚动发生,就会给自己的子view(if instance of Appbarlayout)添加滚动事件。
<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">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
</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">
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
这里同样需要设置这两个属性:
app:layout_scrollFlags="scroll|enterAlways"
app:layout_behavior="@string/appbar_scrolling_view_behavior"