我的CSDN博客同步發(fā)布:玩轉(zhuǎn)AppBarLayout,更酷炫的頂部欄
上一篇文章[《CoordinateLayout的使用如此簡(jiǎn)單 》]上一篇文章《CoordinateLayout的使用如此簡(jiǎn)單 》對(duì)CoordinateLayout
的使用做了講解,今天我們?cè)僦v解常常與其一起使用的幾個(gè)View
:AppBarLayout
、CollapsingToolbarLayout
以及Toolbar
。一下子出現(xiàn)3個(gè)陌生的View
,是不是覺(jué)得很慌張~,很多人都寫(xiě)了這幾個(gè)布局的使用,但是他們卻沒(méi)有有針對(duì)性的單獨(dú)講解每個(gè)View的作用以及如何使用,我看的很多文章都是一上來(lái)就把AppBarLayout
、CollapsingToolbarLayout
以及Toolbar
寫(xiě)到一個(gè)布局里面去,然后一個(gè)一個(gè)布局屬性去說(shuō),一下子感覺(jué)好混亂,本文是從Toolbar開(kāi)始說(shuō)起,最終讓你把這3個(gè)View徹底掌握下來(lái)!
其實(shí),這三個(gè)View都是針對(duì)我們以往常用的ActionBar
的,就是針對(duì)我們的App的頂部的Bar玩各種花樣~我們往下看,看看他們把我們的App的"頂部欄"玩出個(gè)什么花樣!
1 Toolbar
Toobar主要是用來(lái)替換ActionBar的,換句話說(shuō),ActionBar能做的,Toolbar都能做。如果你對(duì)ActionBar的使用比較熟悉,你會(huì)發(fā)現(xiàn)Toolbar使用起來(lái)非常簡(jiǎn)單。ok,既然是替換,當(dāng)然用Toolbar的時(shí)候就得先去把ActionBar給隱藏掉啦~
隱藏ActionBar的方法有很多,可以通過(guò)代碼的方式隱藏,也可以通過(guò)配置文件的方式,我們主要是通過(guò)配置文件的方式來(lái)隱藏。在我們的styles.xml文件中的AppTheme標(biāo)簽中加入如下兩行:
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
當(dāng)然了,你也可以新建一個(gè)<style>
標(biāo)簽,將上面兩行代碼加入,并且將這個(gè)新建的標(biāo)簽作為<application>
的theme
。還可以選擇通過(guò)將AppTheme的parent設(shè)置為Theme.AppCompat.Light.NoActionBar
的方式。方法很多,可以自己隨便選。
接下來(lái)就是將Toolbar放入到布局文件(沒(méi)啥好解釋的):
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
android:layout_height="?android:attr/actionBarSize" />
最后將Toobar作為“ActionBar”來(lái)用
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("這里是Title");
toolbar.setSubtitle("這里是子標(biāo)題");
toolbar.setLogo(R.drawable.icon);
setSupportActionBar(toolbar);
可以對(duì)Toolbar設(shè)置Logo、標(biāo)題、子標(biāo)題等等還有很多其他的設(shè)置,自己去慢慢玩,這里不提啦。當(dāng)然了,也可以在布局文件中設(shè)置這些,在布局文件設(shè)置就不寫(xiě)啦,hongyang大神有篇博客寫(xiě)的挺好的《 Android 5.x Theme 與 ToolBar 實(shí)戰(zhàn) 》可以去參考一下。
看看效果:
如果Toolbar僅僅是用來(lái)對(duì)以往的ActionBar做一次替換,那也太沒(méi)創(chuàng)意啦!完全沒(méi)必要去替換了,因?yàn)樗鼈儽憩F(xiàn)出來(lái)的都是一樣的,而且并沒(méi)有讓我們覺(jué)得用起來(lái)比ActionBar方便。那為啥要替換呢,總應(yīng)該有他的理由吧:ActionBar是固定在頂部,并不能移動(dòng),我覺(jué)得這是最大的不好,而我們的ToolBar可以讓我們隨便擺放,就就可以帶來(lái)很多靈活性和效果啦!
正如你所看的這樣,Toolbar根本就不夠看的,一點(diǎn)都不復(fù)雜。接下來(lái)我們繼續(xù)學(xué)習(xí)在Toolbar上面再套一層父View,讓Toolbar更有互動(dòng)性。
2 AppBarLayout
AppBarLayout繼承自LinearLayout,布局方向?yàn)榇怪狈较?。所以你可以把它?dāng)成垂直布局的LinearLayout來(lái)使用。AppBarLayout是在LinearLayou上加了一些材料設(shè)計(jì)的概念,它可以讓你定制當(dāng)某個(gè)可滾動(dòng)View的滾動(dòng)手勢(shì)發(fā)生變化時(shí),其內(nèi)部的子View實(shí)現(xiàn)何種動(dòng)作。
請(qǐng)注意:上面提到的某個(gè)可滾動(dòng)View,可以理解為某個(gè)ScrollView。怎么理解上面的話呢?就是說(shuō),當(dāng)某個(gè)ScrollView發(fā)生滾動(dòng)時(shí),你可以定制你的“頂部欄”應(yīng)該執(zhí)行哪些動(dòng)作(如跟著一起滾動(dòng)、保持不動(dòng)等等)。那某個(gè)可移動(dòng)的View到底是哪個(gè)可移動(dòng)的View呢?這是由你自己指定的!如何指定,我們后面說(shuō)。
2.1 AppBarLayout子View的動(dòng)作
內(nèi)部的子View通過(guò)在布局中加app:layout_scrollFlags
設(shè)置執(zhí)行的動(dòng)作,那么app:layout_scrollFlags
可以設(shè)置哪些動(dòng)作呢?分別如下:
(1)
scroll
:值設(shè)為scroll
的View會(huì)跟隨滾動(dòng)事件一起發(fā)生移動(dòng)。
什么意思呢?簡(jiǎn)單的說(shuō),就是當(dāng)指定的ScrollView發(fā)生滾動(dòng)時(shí),該View也跟隨一起滾動(dòng),就好像這個(gè)View也是屬于這個(gè)ScrollView一樣。
一張gif足以說(shuō)明:
對(duì)應(yīng)的布局文件
<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="?android:attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll" />
</android.support.design.widget.AppBarLayout>
(2)
enterAlways
:值設(shè)為enterAlways
的View,當(dāng)ScrollView往下滾動(dòng)時(shí),該View會(huì)直接往下滾動(dòng)。而不用考慮ScrollView是否在滾動(dòng)。
看個(gè)動(dòng)畫(huà)片(Y(o)Y)(ToolBar高度設(shè)為:?android:attr/actionBarSize
,app:layout_scrollFlags="scroll|enterAlways"
):
(3)
exitUntilCollapsed
:值設(shè)為exitUntilCollapsed
的View,當(dāng)這個(gè)View要往上逐漸“消逝”時(shí),會(huì)一直往上滑動(dòng),直到剩下的的高度達(dá)到它的最小高度后,再響應(yīng)ScrollView的內(nèi)部滑動(dòng)事件。
怎么理解呢?簡(jiǎn)單解釋:在ScrollView往上滑動(dòng)時(shí),首先是View把滑動(dòng)事件“奪走”,由View去執(zhí)行滑動(dòng),直到滑動(dòng)最小高度后,把這個(gè)滑動(dòng)事件“還”回去,讓ScrollView內(nèi)部去上滑??磦€(gè)gif感受一下(圖中將高度設(shè)的比較大:200dp,并將最小高度設(shè)置為?android:attr/actionBarSize
,app:layout_scrollFlags="scroll|exitUntilCollapsed"
):
(4)
enterAlwaysCollapsed
:是enterAlways
的附加選項(xiàng),一般跟enterAlways
一起使用,它是指,View在往下“出現(xiàn)”的時(shí)候,首先是enterAlways
效果,當(dāng)View的高度達(dá)到最小高度時(shí),View就暫時(shí)不去往下滾動(dòng),直到ScrollView滑動(dòng)到頂部不再滑動(dòng)時(shí),View再繼續(xù)往下滑動(dòng),直到滑到View的頂部結(jié)束。
來(lái)個(gè)gif感受一下(圖中將高度設(shè)的比較大:200dp,并將最小高度設(shè)置為?android:attr/actionBarSize
,app:layout_scrollFlags="scroll|enerAlways|enterAlwaysCollapsed"
):
2.2 將AppBarLayout與ScrollView關(guān)聯(lián)起來(lái)
前面說(shuō)了一直反復(fù)說(shuō)“當(dāng)ScrollView發(fā)生滾動(dòng)時(shí)”,那么怎么將AppBarLayout與ScrollView關(guān)聯(lián)起來(lái)呢?我們注意到,AppBarLayout與ScrollView之間動(dòng)作“相互依賴”,這不就是我們上一篇《CoordinateLayout的使用如此簡(jiǎn)單 》所學(xué)的內(nèi)容嗎?把ScrollView和AppBarLayout作為CoordinateLayout的子View,然后編寫(xiě)一個(gè)Behavior,在這個(gè)Behavior里面判斷當(dāng)前的操作是應(yīng)該讓ScrollView時(shí)刻保持在AppBarLayout之下(即只要改變AppBarLayout的位置就可以一起滑動(dòng)),還是應(yīng)該讓ScrollView內(nèi)部滾動(dòng)而不讓AppBarLayout位置發(fā)生變化等等這些需求,都是可以在Behavior里面處理的。你可以去針對(duì)你的ScrollView編寫(xiě)B(tài)ehavior。然而,我們看到我們的AppBarLayout事先的功能比較復(fù)雜,如果我們自己去定義這樣的效果,代碼非常復(fù)雜,還要考慮很多方面,好在Android幫我們寫(xiě)好啦,我們直接用就是了,這個(gè)ScrollView就是NestedScrollView,請(qǐng)注意,它并沒(méi)有繼承ScrollView,它繼承的是FrameLayout,但是它實(shí)現(xiàn)的效果把它可以看成是ScrollView。
把NestedScrollView放入到我們的layout文件里面就可以啦~~,很方便
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!--將你的內(nèi)容放在這里-->
</android.support.v4.widget.NestedScrollView>
有沒(méi)有注意到有個(gè)屬性:app:layout_behavior="@string/appbar_scrolling_view_behavior"
,它就是指定Behavior的,appbar_scrolling_view_behavior
對(duì)應(yīng)的類的名稱是:android.support.design.widget.AppBarLayout$ScrollingViewBehavior
感興趣的可以去分析源碼。
好了,我們現(xiàn)在會(huì)用AppBarLayout啦~是不是發(fā)現(xiàn)用起來(lái)so easy!接下來(lái)我們把剩下CollapsingToolbarLayout
的給"消化"掉!
3 CollapsingToolbarLayout
CollapsingToolbarLayout
是用來(lái)對(duì)Toolbar
進(jìn)行再次包裝的ViewGroup
,主要是用于實(shí)現(xiàn)折疊(其實(shí)就是看起來(lái)像伸縮~)的App Bar效果。它需要放在AppBarLayout
布局里面,并且作為AppBarLayout
的直接子View
。CollapsingToolbarLayout
主要包括幾個(gè)功能(參照了官方網(wǎng)站上內(nèi)容,略加自己的理解進(jìn)行解釋):
(1) 折疊Title(Collapsing title):當(dāng)布局內(nèi)容全部顯示出來(lái)時(shí),title是最大的,但是隨著View逐步移出屏幕頂部,title變得越來(lái)越小。你可以通過(guò)調(diào)用setTitle函數(shù)來(lái)設(shè)置title。
(2)內(nèi)容紗布(Content scrim):根據(jù)滾動(dòng)的位置是否到達(dá)一個(gè)閥值,來(lái)決定是否對(duì)View“蓋上紗布”。可以通過(guò)setContentScrim(Drawable)來(lái)設(shè)置紗布的圖片.
(3)狀態(tài)欄紗布(Status bar scrim):根據(jù)滾動(dòng)位置是否到達(dá)一個(gè)閥值決定是否對(duì)狀態(tài)欄“蓋上紗布”,你可以通過(guò)
setStatusBarScrim(Drawable)
來(lái)設(shè)置紗布圖片,但是只能在LOLLIPOP
設(shè)備上面有作用。
(4)視差滾動(dòng)子View(Parallax scrolling children):子View可以選擇在當(dāng)前的布局當(dāng)時(shí)是否以“視差”的方式來(lái)跟隨滾動(dòng)。(PS:其實(shí)就是讓這個(gè)View的滾動(dòng)的速度比其他正常滾動(dòng)的View速度稍微慢一點(diǎn))。將布局參數(shù)
app:layout_collapseMode
設(shè)為parallax
(5)將子View位置固定(Pinned position children):子View可以選擇是否在全局空間上固定位置,這對(duì)于Toolbar來(lái)說(shuō)非常有用,因?yàn)楫?dāng)布局在移動(dòng)時(shí),可以將Toolbar固定位置而不受移動(dòng)的影響。 將
app:layout_collapseMode
設(shè)為pin
。
了解這些概念后,我們來(lái)看看布局吧~
<?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:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/main.backdrop"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:scaleType="centerCrop"
android:src="@drawable/material_img"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="50dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/my_txt"
android:textSize="20sp" />
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
上面的都看得懂吧,每個(gè)陌生的屬性都是講過(guò)的哦,忘記了的話回頭看,稍微解釋一下,圖片被設(shè)置為有視差的滑動(dòng),Toolbar設(shè)置為固定不動(dòng),另外,CollapsingToolbarLayout會(huì)對(duì)title進(jìn)行放大和縮小,我們看看效果吧~
如果你希望拖動(dòng)過(guò)程中狀態(tài)欄是透明的,可以在CollapsingToolbarLayout中加 app:statusBarScrim="@android:color/transparent",并且在onCreate中調(diào)用getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)將狀態(tài)欄設(shè)置為透明就好啦~
獻(xiàn)上源碼,請(qǐng)笑納:http://download.csdn.net/detail/huachao1001/9538934