CoodinatorLayout 是Google Material Design 中的一個控件,旨在解決開發中的嵌套滑動與事件分發
簡介
CoordinatorLayout 繼承自 ViewGroup 並實現 NestedScrollingParent 接口,是一個特殊的FrameLayout ,主要功能是協調內部的各個子控件之間的狀態關係(滑動、觸摸事件傳遞),也可以當做FrameLayout使用。
<android.support.design.widget.CoordinatorLayout
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"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways|snap" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_done" />
</android.support.design.widget.CoordinatorLayout>
Toolbar放置在了AppBarLayout裏面,然後在RecyclerView中使用app: layout_behavior 屬性。指定了一個佈局行爲layout_behavior。其中appbar_ scrolling_ view_ behavior 這個字符串也是由Design Support庫提供的。
當AppBarLayout接收到滾動事件的時候,它內部的子控件其實是可以指定如何去影響這些事件的,通過app:layout_ scrollFlags 屬性就能實現。
這裏在Toolbar中添加了一個app: layout_ scrollFlags 屬性,並將這個屬性的值指定成了 scroll| enterAlways |snap。
scroll 表示當RecyclerView向上滾動的時候,Toolbar 會 跟着一起向.上滾動並實現隱藏;
enterAlways 表示當RecyclerView向下滾動的時候,Toolbar 會 跟着一起向下滾動並重新顯示。
snap表示當Toolbar還沒有完全隱藏或顯示的時候,會根據當前 滾動的距離,自動選擇是隱藏還是顯示。
注意:這裏的佈局行爲和滾動事件怎麼響應得好好研究一下。
屬性解析
1.layout_scrollFlags:
scroll:孩子視圖伴隨滾動事件而滾出或滾進屏幕; 所有想滾動出屏幕的view都需要設置這個flag,沒有設置這個flag的view將被固定在屏幕頂部。例如,TabLayout 沒有設置這個值,將會停留在屏幕頂部。
enterAlways:向下滾動時Scrolling View和Child View之間的滾動優先級,當優先滾動的一方全部滾進屏幕之後,另一方纔開始滾動; 設置這個flag時,向下的滾動都會導致該view變爲可見,啓用快速“返回模式”。
enterAlwaysCollapsed:enterAlways的附加值,這裏涉及到孩子視圖的高度和最小高度,向下滾動時,孩子視圖會先向下滾動至最小高度值,然後Scrolling View纔開始滾動,到達邊界時,孩子視圖再向下滾動,直至顯示完全; 當你的視圖已經設置minHeight屬性又使用此標誌時,你的視圖只能已最小高度進入,只有當滾動視圖到達頂部時才擴大到完整高度。
exitUtilCollapsed:這裏也涉及最小高度,發生向上滾動事件時,孩子視圖向上滾動退出直至最小高度,然後Scrolling View開始滾動,也就是,Child View不會完全退出屏幕; 滾動退出屏幕,最後摺疊在頂端。(可摺疊的標題欄用到了這個屬性)
snap:簡單理解,就是Child View的一個吸附效果,也就是說,Child View不會存在局部顯示的情況,滾動Child View的部分高度,當我們鬆開手指時,Child View 要麼向上全部滾出屏幕,要麼向下全部滾進屏幕,有點類似ViewPager的左右滑動。
原理解析
CoordinatorLayout 能實現滾動事件的處理,關鍵是它實現了NestedScrollingParent,能接受到子view(實現NestedScrollingChild)的滑動事件,然後再把有關滑動的信息傳遞給子view的behavior進行處理消費,最終實現了嵌套滑動,CoordinatorLayout在整個過程中只是相當於一個分發者,沒有做任何關於嵌套滑動的事情。
實現嵌套滑動的關鍵是四個類(接口):
NestedScrollingChild
NestedScrollingParent
NestedScrollingChildHelper
NestedScrollingParentHelper
所以要實現嵌套滑動效果一般使用NestedScrollView或者RecyclerView等實現NestedScrollingChild接口的view。
layout_behavior這個可以自定義,後續得加上。