1. 程式人生 > >【Android】Material Design 之四 五 六 AppBarLayout、CoordinatorLayout、CollapsingToolbarLayout使用

【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)中的問題。

說了這麼多,具體還是要自己動手去實練一遍才有感覺。