简介
还是先来看下 AppBarLayout 文档:
从文档中可以看出,AppBarLayout 存在于 design 包中,是一个垂直布局的 LinearLayout,并且添加了许多材料设计的概念,其主要功能是可以让其子View
可以响应对位于与 AppBarLayout 同一层级的某个可滚动View
(可理解为 ScrollView
)的滚动事件(也就是说,当与 AppBarLayout 同一层级的某个可滚动View
发生滚动时,你可以定制让 AppBarLayout 的子View
响应这些滚动事件(比如让子View
发生滚动,或者保持不动等等)。
AppBarLayout 使用
从上面的讲述中,我们可以概括出 AppBarLayout 最主要的3个方面内容:
-
功能:作为父布局,让其子
View
能够响应与 AppBarLayout 的兄弟节点(ScrollView
)的滚动事件。 -
可滚动
View
:作为 AppBarLayout 的兄弟节点,共享其滚动事件。 -
子
View
:作为 AppBarLayout 的子控件,响应其传递过来的外部ScrollView
的滚动事件。
所以, AppBarLayout 其实更多的是作为一个中介,讲兄弟节点的滚动事件传递给到其子View
,让子View
响应这些事件。
因此,上述这个过程其实涉及到了几个重点需要实现的步骤:
-
AppBarLayout 如何与兄弟节点(
ScrollView
)进行绑定,进而接收到其滚动事件:
让我们再拆分一下这个逻辑,其实就是 AppBarLayout 要与同一层级的ScrollView
进行交互。
如果大家对我们前面讲的
Material Design系列教程(4) - CoordinatorLayout 有映像的话,就知道 CoordinatorLayout 的作用就是提供子View
之间的交互。因此,通过使用 CoordinatorLayout 包裹 AppBarLayout 和ScrollView
,并提供适当的 Behavior,就可以完成这两者的交互了。而这个 Behavior 就是 AppBarLayout.ScrollingViewBehavior,我们可以直接为ScrollView
绑定这个 AppBarLayout.ScrollingViewBehavior(绑定的方法可以通过配置xml文件:app:layout_behavior="@string/appbar_scrolling_view_behavior"
,这个 Google 为我们提供的appbar_scrolling_view_behavior
其实就是 AppBarLayout.ScrollingViewBehavior 的类名:android.support.design.widget.AppBarLayout$ScrollingViewBehavior
),这样,AppBarLayout 就能接收到ScrollView
的滚动事件了。 -
如何定制子
View
响应滚动的行为,并且其行为都有哪些:
当我们绑定了 AppBarLayout 与ScrollView
之后,AppBarLayout 就可以接收到ScrollView
的滚动事件了,那么 AppBarLayout 又是如何将这些滚动事件传递给相应子View
呢,并且响应的行为又有哪些呢?其实,只需通过在代码里调用子View
的setScrollFlags(int)
或者为相应子View
配置app:layout_scrollFlags
属性,就可以实现子View
响应外部ScrollView
的滚动事件,并且其行为有以下几种:
1)scroll:子View
会跟随滚动事件一起发生移动。效果就如同子View
是与ScrollView
一体。
具体效果如下图所示:app:layout_scrollFlags="scroll"
从效果图中可以看到,app:layout_scrollFlags="scroll"
的效果就是:当ScrollView
滚动时, AppBarLayout 的子View
也跟随一起滚动,就好像子View
是隶属于ScrollView
一样。
2)enterAlways:当ScrollView
向下 滚动时,子View
会向下 滚动,直到达到最小高度。
效果图如下:app:layout_scrollFlags="scroll|enterAlways"
简单的说,enterAlways
的效果就是:向下滚动时,当 AppBarLayout 未达到其最小高度时,滚动事件由其子View
消费(即子View
滚动);当达到最小高度后,滚动事件由ScrollView
消费(即ScrollView
滚动)。
结合scroll|enterAlways
可以达到的效果就是:ScrollView
向上滚动时,Toolbar(AppBarLayout 子View
)移出屏幕;ScrollView
向下滚动时,Toolbar 进入屏幕。
3)enterAlwaysCollapsed:该选项是enterAlways
的附加选项,一般跟enterAlways
一起使用,它的效果是:当ScrollView
向下滚动时,子View
会向下滚动,直到达到最小高度(到此为止是enterAlways
的效果),然后当ScrollView
滚动到顶部时,子View
又会响应滚动事件,继续向下滚动,直到子View
完全显示。
效果图如下:app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
,这里为了让效果出现,将子View
大小设置为200dp
。
简单的说,enterAlwaysCollapsed
的效果就是:向下滚动时,滚动事件由其子View
消费(即子View
滚动),直到达到子View
的最小高度;当达到最小高度后,滚动事件由ScrollView
消费(即ScrollView
滚动),直到达到ScrollView
的顶部;当达到ScrollView
的顶部时,滚动事件由子View
消费(即子View
滚动),直到子View
完全显示。
4)exitUntilCollapsed:当ScrollView
向上 滚动时,子View
会向上 滚动,直到达到最小高度。
效果图如下:app:layout_scrollFlags="scroll|exitUntilCollapsed"
,这里为了让效果出现,将子View
大小设置为200dp
。
简单的说,exitUntilCollapsed
的效果就是:向上滚动时,当 AppBarLayout 的子View
未达到其最小高度时,滚动事件由子View
消费(即子View
滚动);当达到最小高度后,滚动事件由ScrollView
消费(即ScrollView
滚动)。
5)snap:该选项效果为:当我们滑动ScrollView
时,如果此时ScrollView
位于顶部,那么滚动事件由 AppBarLayout 的子View
接收;当 AppBarLayout 滑出屏幕的部分大于剩余可视区域,松开手指, AppBarLayout 就会自动滑出屏幕;当 AppBarLayout 滑出屏幕的部分小于剩余可视区域,松开手指, AppBarLayout 就会自动滑进屏幕。
效果图如下:app:layout_scrollFlags="scroll|snap"
注:AppBarLayout 的子View
的layout_scrollFlags
都要加上scroll
,否则没有效果。
总结
AppBarLayout 的作用就是用来定制其子View
响应外部兄弟节点的可滚动View
的滚动事件。子View
响应的行为总共有5种:
-
scroll:子
View
随ScrollView
一起滚动。 -
enterAlways:只要
ScrollView
向下移动,子View
立即响应滚动,直到达到最小高度。 -
enterAlwaysCollapsed:当
ScrollView
滚动到最顶层时,子View
响应滚动事件,直至子View
完全显示。 -
exitUntilCollapsed:只要
ScrollView
向上滚动,子View
立即响应滚动,直到达到最小高度。 -
snap:当
ScrollView
滚动到最顶层时,子View
响应滚动事件。松开手指时,依据 AppBarLayout 移出屏幕区域与剩余可视区域(留在屏幕内的区域)对比,自动移向占比大的区域(即移出屏幕区域大, AppBarLayout 自动移出屏幕;可视区域大,自动完全显示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"
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="200dp"
android:background="?attr/colorPrimary"
android:minHeight="?android:attr/actionBarSize"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title="I am Toolbar"
app:titleMarginTop="140dp"
app:titleTextAppearance="@style/ToolbarTitle">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<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/large_text" />
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
网友评论