【Android】Material Design 之四 五 六 AppBarLayout、CoordinatorLayout、CollapsingToolbarLayout使用
一、AppBarLayout
AppBarLayout是繼承自LinearLayout,預設是垂直方向,可以看成是一個垂直方向的線性佈局,其作用是將APPBarLayout包裹的內容都作為AppBar,支援手勢滑動。
AppBarLayout必須作為Toolbar的父佈局容器,換句話就是說,使用AppBarLayout佈局時,需要包裹Toolbar佈局。
支援手勢滑動時,需要和CoordinatorLayout配合使用。
二、CoordinatorLayout
CoordinatorLayout是一個為子檢視之間相互協調手勢效果的協調佈局, 在不指定檢視位置時,和FrameLayout一樣,所有檢視都位於在左上角。一般都是和AppBarLayout 、CollapsingToolbarLayout配合使用。
三、CollapsingToolbarLayout
CollapsingToolbarLayout一般作為AppBarLayout的子檢視使用,當其包裹Toolbar時,提供了一個可以摺疊的Toolbar,需要有摺疊效果的元件還需設定 layout_collapseMode屬性。是繼承自FrameLayout佈局,如果包裹的檢視不指定位置,會和FrameLayout一樣位於在左上角。
使用上面這些佈局,都要匯入Material Design依賴包,我使用的是Android Studio 3.0版本,匯入包
implementation 'com.android.support:design:28.0.0-alpha1'
四、使用 CoordinatorLayout + RecyclerView + AppBarLayout +( Toolbar) 實現Toolbar可手勢滑動
(1)自定義一個Toolbar佈局toolbar_layout.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="?actionBarSize"> <ImageView android:id="@+id/iv" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="10dp" android:src="@drawable/toolbar_pic" android:layout_centerVertical="true"/> <LinearLayout android:id="@+id/ll_title" android:layout_toRightOf="@+id/iv" android:layout_marginLeft="10dp" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="主標題" android:textSize="15sp" android:textColor="#000000" android:padding="5dp"/> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="副標題" android:textSize="13sp" android:textColor="#ece8e8" android:padding="5dp"/> </LinearLayout> <ImageView android:id="@+id/iv2" android:layout_toLeftOf="@+id/iv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_search" android:layout_centerVertical="true" android:layout_marginRight="10dp"/> <ImageView android:id="@+id/iv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_more" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:layout_marginRight="10dp"/> </RelativeLayout>
(2)activity_app_bar_layout.xml
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SAppBarLayoutActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/appbarlayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" app:layout_scrollFlags="scroll|enterAlways"> <include layout="@layout/toolbar_layout"/> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="android.support.v7.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>
(3)RecyclerView的介面卡
public class RVMyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private Context context; private List<String> list; public RVMyAdapter(Context context, List<String> list) { this.context = context; this.list = list; } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { TextView textView=new TextView(context); return new RecyclerView.ViewHolder(textView) {}; } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) { ((TextView)viewHolder.itemView).setText(list.get(i)); } @Override public int getItemCount() { return list.size(); } }
(4)AppBarLayoutActivity.java
public class AppBarLayoutActivity extends Activity { private Toolbar toolbar; private RecyclerView recyclerView; private List<String> list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sapp_bar_layout); //設定toolbart替代ActionBar toolbar=findViewById(R.id.toolbar); setSupportActionBar(toolbar); //設定recyclerView填充資料 recyclerView=findViewById(R.id.recyclerView); list=new ArrayList<>(); for (int i = 0; i < 1000; i++) { list.add(String.format(Locale.CHINA,"第%03d條資料",i)); } recyclerView.setAdapter(new RVMyAdapter(this,list)); } }
(5)執行介面
(6)效果實現說明:
為了使Toolbar可以手勢滑動,首先,給Toolbar設定app:layout_scrollFlags="scroll | enterAlways"屬性。其次,CoordinatorLayout佈局下必須包裹一個可以滑動的佈局,比如,可以是RecyclerView(經測試,ListView、ScrollView不支援) , 並且給這滑動元件設定屬性app:layout_behavior="@string/appbar_scrolling_view_behavior"來告訴CoordinatorLayout,該元件是帶有滑動行為的元件,然後CoordinatorLayout在接收到滑動時會通知AppBarLayout 中可滑動的Toolbar可以滑出螢幕了。
給想要實現手勢滑動的元件設定的layout_scrollFlags屬性有如下幾種選項:
scroll: 所有想滾動出螢幕的view都需要設定這個值,沒有設定這個值的view將被固定在螢幕頂部。enterAlways: 任意向下的滾動都會導致該view變為可見,啟用快速“返回模式”。 enterAlwaysCollapsed: 當滾動檢視到達頂部時view才擴大到完整高度。exitUntilCollapsed: 滾動退出螢幕,最後摺疊在頂端。
(7)總結
為了使Toolbar有手勢滑動的效果,必須做到下面幾點:
1、CoordinatorLayout作為整個佈局的父佈局容器
2、Toolbar的父佈局容器須為AppBarLayout,給Toolbar設定屬性
app:layout_scrollFlags=" ",值為scroll|enterAlways表示滾動出螢幕|任意向下滑動就可見,值為scroll|enterAlwaysCollapsed表示滾動出螢幕|向下滑動頂端出現才可見
3、CoordinatorLayout需包裹一個滑動元件,比如RecyclerView,並給滑動元件設定屬性:
app:layout_behavior="@string/appbar_scrolling_view_behavior"
(8)擴充套件一下,稍稍修改下activity_app_bar_layout.xml佈局,在AppBarLayout中增加一個ImageView控制元件,其他地方不變
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SAppBarLayoutActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/appbarlayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <ImageView android:layout_width="80dp" android:layout_height="80dp" android:layout_gravity="center" android:paddingTop="10dp" android:src="@drawable/toolbar_pic" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" app:layout_scrollFlags="scroll|enterAlways"> <include layout="@layout/toolbar_layout"/> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="android.support.v7.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>
介面如下圖所示,執行中我們可以發現,這種情況下,即使Toolbar設定了屬性app:layout_scrollFlags="scroll | enterAlways",RecyclerView在滑動過程中Toolbar也沒有出現滑動。如果將app:layout_scrollFlags="scroll | enterAlways"屬性設定給AppBarLayout,Toolbar仍然沒有滑動。如果將app:layout_scrollFlags="scroll | enterAlways"屬性設定給剛新增的ImageView,ImageView卻出現了滑動,向上滑動時Toolbar會固定在頂部位置。如果這種情況想要實現Toolbar也可滑動,怎麼辦?這個問題將會在下面給出解決。
五、使用 CoordinatorLayout + RecyclerView + AppBarLayout + (CollapsingToolbarLayout +( ToolBar) ) 實現可摺疊的Toolbar
(1)CollapsingToolbarLayout的常用屬性
app:contentScrim="@color/colorAccent" //設定被摺疊到頂部固定時候的背景
app:layout_scrollFlags="scroll | exitUntilCollapsed" //設定滑動標誌 scroll: 所有想滾動出螢幕的view都需要設定這個值,exitUntilCollapsed: 滾動退出螢幕,最後摺疊在頂端。
app:layout_collapseParallaxMultiplier="0.2" //設定CollapsingToolbarLayout滑動時其子檢視的視覺差
app:layout_collapseMode="parallax" // 設定子檢視的摺疊模式 “pin”:固定模式,在摺疊的時候最後固定在頂端;“parallax”:視差模式,在摺疊的時候會有個視差摺疊的效果。
(2)自定義的toolbar_layout佈局、程式碼檔案、RecyclerView介面卡檔案與上面的一樣,這裡就不重複貼了,這裡只貼一下佈局檔案。
(3)佈局檔案
<?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".AppBarLayoutActivity"> <android.support.design.widget.AppBarLayout android:id="@+id/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:contentScrim="@color/colorAccent" app:layout_collapseParallaxMultiplier="0.2" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:layout_collapseMode="parallax"> <ImageView android:layout_width="80dp" android:layout_height="200dp" android:layout_gravity="center" android:src="@drawable/toolbar_pic" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?actionBarSize" android:layout_gravity="bottom"> <include layout="@layout/toolbar_layout"/> </android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="android.support.v7.widget.LinearLayoutManager" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </android.support.v7.widget.RecyclerView> </android.support.design.widget.CoordinatorLayout>
(5)執行介面
(6)注意:Toolbar的高度layout_height必須固定,不能是“wrap_content”,否則Toolbar不會滑動,也不會摺疊。
(7)擴充套件:如果將CollapsingToolbarLayout的屬性app:layout_scrollFlags=""設定為scroll | enterAlways,就會實現可滑動的ImageView+Toolbar,這剛好可以解決四(7)中的問題。
說了這麼多,具體還是要自己動手去實練一遍才有感覺。