先看效果。
源碼:GitHub地址
實(shí)現(xiàn)與分析
很顯然,這樣的效果用到了Android Material Design里的控件,分別是CoordinatorLayout和AppBarLayout。其中,AppBarLayout控件便具備頂部固定的功能,但它需要被CoordinatorLayout嵌套起來才能實(shí)現(xiàn)滾動固定的效果,否則無效。
上面效果圖的Layout代碼如下:
<?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:focusable="true"
android:focusableInTouchMode="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/abl_head"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:translationZ="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:minHeight="50dp"
android:orientation="vertical"
app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlways|snap">
<include layout="@layout/layout_hidden_bar" />
<include layout="@layout/layout_stick_bar" />
</LinearLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
其中include進(jìn)來的@layout/layout_hidden_bar和@layout/layout_stick_bar就是效果圖中頂部的可隱藏布局和固定布局。都是簡單色塊+文本,就不展示xml源碼了。
上面的實(shí)現(xiàn),關(guān)鍵的在于LinearLayout的兩個(gè)屬性:
app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlways|snap"
android:minHeight="50dp" // 其中50dp是指@layout/layout_stick_bar的高度
先說說app:layout_scrollFlags屬性。
查看源碼知道,CoordinatorLayout實(shí)現(xiàn)了NestedScrollingParent2接口,它支持對所嵌套的子控件滾動時(shí)進(jìn)行響應(yīng)控制。用CoordinatorLayout包含了整個(gè)界面,在界面滾動時(shí),所有控件都會根據(jù)CoordinatorLayout的滾動實(shí)現(xiàn)方法進(jìn)行動態(tài)排版。這才有AppBarLayout在滾動時(shí)的折疊置頂效果,如果離開CoordinatorLayout控件,AppBarLayout便不具備這樣的效果。
app:layout_scrollFlags屬性指明了LinearLayout在AppBarLayout中滾動時(shí)狀態(tài)。其中:
- scroll
滾動時(shí)響應(yīng)。如果不加上這個(gè)屬性值,界面滾動時(shí),頂部內(nèi)容將不會隨滾動折疊或變化。
- exitUntilCollapsed
Scroll Up: the view is always visible, provided its height is > 0 and the expanded version (e.g. Toolbar with an ImageView) will become visible when scrolled all the way up
Scroll Down: the view scrolls with the rest of the layout's content, but only till its collapsed state (hence - "exit until collapsed"), so in case of a Toolbar with a fixed height, it will always be visible on the top
界面在向上滾動時(shí),如果有指定最小高度,指定最小高度的頂部布局內(nèi)容會保持可見(即置頂)。向下移動,剩余的內(nèi)容會跟著顯示出來。
如果沒有設(shè)置這個(gè)屬性,頂部內(nèi)容將會隨向上滾動而滾動,至最終消失。
- enterAlways
頂部布局總是進(jìn)入。如果設(shè)定這個(gè)屬性,無論在哪個(gè)地方只要界面向下滾動,頂部內(nèi)容都會跟著滾下來。如果沒有設(shè)定,則需要滾動到界面最頂部后,頂部布局才會出現(xiàn)。
- snap
Scroll Up AND Down fast scrolls up or down based on how much of the view is visible - if more than 50% - the view will scroll down, showing itself, if less - the view will hide; used with other flags as a further customization
吸附顯示。設(shè)置這個(gè)值后,隱藏的內(nèi)容被拖出超過50%時(shí),松開手就會自動顯示整個(gè)布局;相反,顯示的布局被隱藏超過50%時(shí),松開手就會自動隱藏整個(gè)布局。
可以看到,我們都設(shè)置了這四個(gè)屬性。
設(shè)置exitUntilCollapsed屬性值后,還要設(shè)置頂部布局的最小高度,否則頂部的所有內(nèi)容仍會隨界面的向上滾動而全部隱藏(因?yàn)樽钚「叨饶J(rèn)為0)。上面效果圖中,頂部布局的最小高度是50dp,也就是固定視圖@layout/layout_stick_bar的高度。
另外,為了讓recyclerView附著在AppBarLayout下面,需要對其設(shè)置app:layout_behavior屬性,
app:layout_behavior="@string/appbar_scrolling_view_behavior"
其中@string/appbar_scrolling_view_behavior的值為:
<string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>
大致作用是使recyclerView附著著AppBarLayout的滾動。具體實(shí)現(xiàn)待深究。