安卓高階6 玩轉AppBarLayout,更酷炫的頂部欄 Toolbar
原文大神地址:http://www.jianshu.com/p/d159f0176576
上一篇文章[《CoordinateLayout的使用如此簡單 》]上一篇文章《CoordinateLayout的使用如此簡單 》對CoordinateLayout
的使用做了講解,今天我們再講解常常與其一起使用的幾個View
:AppBarLayout
、CollapsingToolbarLayout
以及Toolbar
。一下子出現3個陌生的View
,是不是覺得很慌張~,很多人都寫了這幾個佈局的使用,但是他們卻沒有有針對性的單獨講解每個View的作用以及如何使用,我看的很多文章都是一上來就把AppBarLayout
、CollapsingToolbarLayout
Toolbar
寫到一個佈局裡面去,然後一個一個佈局屬性去說,一下子感覺好混亂,本文是從Toolbar開始說起,最終讓你把這3個View徹底掌握下來!其實,這三個View都是針對我們以往常用的ActionBar
的,就是針對我們的App的頂部的Bar玩各種花樣~我們往下看,看看他們把我們的App的"頂部欄"玩出個什麼花樣!
1 Toolbar
Toobar主要是用來替換ActionBar的,換句話說,ActionBar能做的,Toolbar都能做。如果你對ActionBar的使用比較熟悉,你會發現Toolbar使用起來非常簡單。ok,既然是替換,當然用Toolbar的時候就得先去把ActionBar給隱藏掉啦~
隱藏ActionBar的方法有很多,可以通過程式碼的方式隱藏,也可以通過配置檔案的方式,我們主要是通過配置檔案的方式來隱藏。在我們的styles.xml檔案中的AppTheme標籤中加入如下兩行:
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
當然了,你也可以新建一個<style>
標籤,將上面兩行程式碼加入,並且將這個新建的標籤作為<application>
的theme
。還可以選擇通過將AppTheme的parent設定為Theme.AppCompat.Light.NoActionBar
接下來就是將Toolbar放入到佈局檔案(沒啥好解釋的):
<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”來用
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("這裡是Title");
toolbar.setSubtitle("這裡是子標題");
toolbar.setLogo(R.drawable.icon);
setSupportActionBar(toolbar);
可以對Toolbar設定Logo、標題、子標題等等~還有很多其他的設定,自己去慢慢玩,這裡不提啦~。當然了,也可以在佈局檔案中設定這些,在佈局檔案設定就不寫啦,hongyang大神有篇部落格寫的挺好的《 Android 5.x Theme 與 ToolBar 實戰 》可以去參考一下。
看看效果:
Toolbar
如果Toolbar僅僅是用來對以往的ActionBar做一次替換,那也太沒創意啦!完全沒必要去替換了,因為它們表現出來的都是一樣的,而且並沒有讓我們覺得用起來比ActionBar方便。那為啥要替換呢,總應該有他的理由吧:ActionBar是固定在頂部,並不能移動,我覺得這是最大的不好,而我們的ToolBar可以讓我們隨便擺放,就就可以帶來很多靈活性和效果啦!
正如你所看的這樣,Toolbar根本就不夠看的,一點都不復雜。接下來我們繼續學習在Toolbar上面再套一層父View,讓Toolbar更有互動性。
2 AppBarLayout
AppBarLayout繼承自LinearLayout,佈局方向為垂直方向。所以你可以把它當成垂直佈局的LinearLayout來使用。AppBarLayout是在LinearLayou上加了一些材料設計的概念,它可以讓你定製當某個可滾動View的滾動手勢發生變化時,其內部的子View實現何種動作。
請注意:上面提到的某個可滾動View,可以理解為某個ScrollView。怎麼理解上面的話呢?就是說,當某個ScrollView發生滾動時,你可以定製你的“頂部欄”應該執行哪些動作(如跟著一起滾動、保持不動等等)。那某個可移動的View到底是哪個可移動的View呢?這是由你自己指定的!如何指定,我們後面說。
2.1 AppBarLayout子View的動作
內部的子View通過在佈局中加app:layout_scrollFlags
設定執行的動作,那麼app:layout_scrollFlags
可以設定哪些動作呢?分別如下:
(1)
scroll
:值設為scroll
的View會跟隨滾動事件一起發生移動。
什麼意思呢?簡單的說,就是當指定的ScrollView發生滾動時,該View也跟隨一起滾動,就好像這個View也是屬於這個ScrollView一樣。
一張gif足以說明:
scroll
對應的佈局檔案
<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
:值設為enterAlways
的View,當ScrollView往下滾動時,該View會直接往下滾動。而不用考慮ScrollView是否在滾動。
看個動畫片(Y(^o^)Y)(ToolBar高度設為:?android:attr/actionBarSize
,app:layout_scrollFlags="scroll|enterAlways"
):
scroll|enterAlways
(3)
exitUntilCollapsed
:值設為exitUntilCollapsed
的View,當這個View要往上逐漸“消逝”時,會一直往上滑動,直到剩下的的高度達到它的最小高度後,再響應ScrollView的內部滑動事件。
怎麼理解呢?簡單解釋:在ScrollView往上滑動時,首先是View把滑動事件“奪走”,由View去執行滑動,直到滑動最小高度後,把這個滑動事件“還”回去,讓ScrollView內部去上滑。看個gif感受一下(圖中將高度設的比較大:200dp,並將最小高度設定為?android:attr/actionBarSize
,app:layout_scrollFlags="scroll|exitUntilCollapsed"
):
scroll|exitUntilCollapsed
(4)
enterAlwaysCollapsed
:是enterAlways
的附加選項,一般跟enterAlways
一起使用,它是指,View在往下“出現”的時候,首先是enterAlways
效果,當View的高度達到最小高度時,View就暫時不去往下滾動,直到ScrollView滑動到頂部不再滑動時,View再繼續往下滑動,直到滑到View的頂部結束。
來個gif感受一下(圖中將高度設的比較大:200dp,並將最小高度設定為?android:attr/actionBarSize
,app:layout_scrollFlags="scroll|enerAlways|enterAlwaysCollapsed"
):
scroll|enerAlways|enterAlwaysCollapsed
2.2 將AppBarLayout與ScrollView關聯起來
前面說了一直反覆說“當ScrollView發生滾動時”,那麼怎麼將AppBarLayout與ScrollView關聯起來呢?我們注意到,AppBarLayout與ScrollView之間動作“相互依賴”,這不就是我們上一篇《CoordinateLayout的使用如此簡單 》所學的內容嗎?把ScrollView和AppBarLayout作為CoordinateLayout的子View,然後編寫一個Behavior,在這個Behavior裡面判斷當前的操作是應該讓ScrollView時刻保持在AppBarLayout之下(即只要改變AppBarLayout的位置就可以一起滑動),還是應該讓ScrollView內部滾動而不讓AppBarLayout位置發生變化等等這些需求,都是可以在Behavior裡面處理的。你可以去針對你的ScrollView編寫Behavior。然而,我們看到我們的AppBarLayout事先的功能比較複雜,如果我們自己去定義這樣的效果,程式碼非常複雜,還要考慮很多方面,好在Android幫我們寫好啦,我們直接用就是了,這個ScrollView就是NestedScrollView,請注意,它並沒有繼承ScrollView,它繼承的是FrameLayout,但是它實現的效果把它可以看成是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">
<!--將你的內容放在這裡-->
</android.support.v4.widget.NestedScrollView>
有沒有注意到有個屬性:app:layout_behavior="@string/appbar_scrolling_view_behavior"
,它就是指定Behavior的,appbar_scrolling_view_behavior
對應的類的名稱是:android.support.design.widget.AppBarLayout$ScrollingViewBehavior
感興趣的可以去分析原始碼。
好了,我們現在會用AppBarLayout啦~是不是發現用起來so easy!接下來我們把剩下CollapsingToolbarLayout
的給"消化"掉!
3 CollapsingToolbarLayout
CollapsingToolbarLayout
是用來對Toolbar
進行再次包裝的ViewGroup
,主要是用於實現摺疊(其實就是看起來像伸縮~)的App Bar效果。它需要放在AppBarLayout
佈局裡面,並且作為AppBarLayout
的直接子View
。CollapsingToolbarLayout
主要包括幾個功能(參照了官方網站上內容,略加自己的理解進行解釋):
(1) 摺疊Title(Collapsing title):當佈局內容全部顯示出來時,title是最大的,但是隨著View逐步移出螢幕頂部,title變得越來越小。你可以通過呼叫setTitle函式來設定title。
(2)內容紗布(Content scrim):根據滾動的位置是否到達一個閥值,來決定是否對View“蓋上紗布”。可以通過setContentScrim(Drawable)來設定紗布的圖片.
(3)狀態列紗布(Status bar scrim):根據滾動位置是否到達一個閥值決定是否對狀態列“蓋上紗布”,你可以通過
setStatusBarScrim(Drawable)
來設定紗布圖片,但是隻能在LOLLIPOP
裝置上面有作用。(4)視差滾動子View(Parallax scrolling children):子View可以選擇在當前的佈局當時是否以“視差”的方式來跟隨滾動。(PS:其實就是讓這個View的滾動的速度比其他正常滾動的View速度稍微慢一點)。將佈局引數
app:layout_collapseMode
設為parallax
(5)將子View位置固定(Pinned position children):子View可以選擇是否在全域性空間上固定位置,這對於Toolbar來說非常有用,因為當佈局在移動時,可以將Toolbar固定位置而不受移動的影響。 將
app:layout_collapseMode
設為pin
。
瞭解這些概念後,我們來看看佈局吧~
<?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>
上面的都看得懂吧,每個陌生的屬性都是講過的哦,忘記了的話回頭看,稍微解釋一下,圖片被設定為有視差的滑動,Toolbar設定為固定不動,另外,CollapsingToolbarLayout會對title進行放大和縮小,我們看看效果吧~
CollapsingToolbarLayout效果
如果你希望拖動過程中狀態列是透明的,可以在CollapsingToolbarLayout中加 app:statusBarScrim="@android:color/transparent",並且在onCreate中呼叫getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)將狀態列設定為透明就好啦~
以下內容樣式非原作者編寫
1 設定選單
// 設定選單
toolBar.inflateMenu(R.menu.menu_tool);
toolBar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
int itemId = item.getItemId();
switch (itemId) {
case R.id.item1:
Toast.makeText(MainActivity.this, "條目一", Toast.LENGTH_SHORT).show();
break;
case R.id.item2:
Toast.makeText(MainActivity.this, "條目二", Toast.LENGTH_SHORT).show();
break;
case R.id.item3:
Toast.makeText(MainActivity.this, "條目三", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
2 設定展開時標題顏色
private CollapsingToolbarLayout mCollapsingToolbarLayout;
//展開時 標題顏色mCollapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);
//摺疊時標題的顏色mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.BLUE);
3.其他樣式
app:contentScrim="#00ff00"設定ToolBar顏色-->
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="10dp"
app:contentScrim="#00ff00"
app:expandedTitleGravity="bottom|right"
app:expandedTitleMargin="@dimen/activity_horizontal_margin"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<!--
app:layout_collapseMode="parallax"
parallax:視差模式 在摺疊的時候 會有視差的摺疊效果
layout_collapseParallaxMultiplier:視差因子1-0
pin:固定模式 滑動的時候 會固定到 螢幕頂端
//展開時標題位置和margin
app:expandedTitleGravity="bottom|right"
app:expandedTitleMargin="@dimen/activity_horizontal_margin"
-->
> 注意:
CollapsingToolbarLayout 巢狀toolbar時不能單有(需要一個兄弟view型別隨意),不然看不見標題
app:layout_scrollFlags="scroll|exitUntilCollapsed"屬性只能在
CollapsingToolbarLayout 寫生效
toolbar 屬性:
collapseMode 設定為pin時候可以看到圖片
如果兄弟節點collapseMode設定為prarallax可以看到壓縮感覺文/huachao1001(簡書作者)
原文連結:http://www.jianshu.com/p/d159f0176576
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。