Android CollapsingToolbarLayout 和ToolBar多種實踐

項目原因?qū)е玛P(guān)于Toolbar的實踐筆記一拖再拖…都快忘記實現(xiàn)的過程了( - - ! )。之前粗略用過CollapsingToolbarLayout 記錄自己實現(xiàn)的簡便版的RecyclerView,不過項目中再次用到的時候還有不少磕磕絆絆。

效果:

first.gif

布局

頭部背景是我隨便切的一個圖片。首先明確一點:整體伸縮布局是包裹在CoordinatorLayout中的,并且非頭部的部分,不論是FrameLayout還是RecyclerView或者其他的View,都需要添加屬性:app:layout_behavior="@string/appbar_scrolling_view_behavior"

  • 這里展開一點題外話,我們在網(wǎng)上尋找到的CoordinatorLayout的相關(guān)資料,可能一般看到的基本XML布局是這樣的:
<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"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

    </android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>

其中CoordinatorLayout用到的屬性:
android:fitsSystemWindows="true"
需要注意使用場景。
可以看到圖中我用了多個Fragment,其他的部分Fragment的布局中我也同樣使用了android:fitsSystemWindows="true"這個屬性,但是在項目全局的主題中,我已經(jīng)設(shè)置了"no titlebar"。設(shè)置以上屬性以后,會導(dǎo)致狀態(tài)欄會自動調(diào)整view的padding以便給system windows留出空間,多個同級布局使用此參數(shù),將導(dǎo)致 切換過程布局抖動。
我建議如已經(jīng)隱掉系統(tǒng)的titlebar的布局或者Activity,就無需設(shè)置這個屬性了。
這里有個關(guān)于設(shè)置android:fitsSystemWindows屬性的效果圖,可以看一下:fitsSystemWindows

我們接著來看整體布局:

<?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:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#66ffffff">
        <!-- 頭部的布局 -->
    </android.support.design.widget.AppBarLayout>
<!-- 主題的布局 -->
    <com.jinqiang.RecyclerViewRefresh.IRecyclerView
        android:id="@+id/recyclerview"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</android.support.design.widget.CoordinatorLayout>

不論主題布局的層級如何,設(shè)置app:layout_behavior="@string/appbar_scrolling_view_behavior"就可以使CoordinatorLayout計算滑動子view了。

toolbar

toolbar 中的頭部布局,要控制哪塊布局是需要滑動效果,哪些是不需要的,這里有個XML對屬性的說明比較清晰:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- 為了使得Toolbar有滑動效果,必須做到如下三點:
          CoordinatorLayout必須作為整個布局的父布局容器。
          給需要滑動的組件設(shè)置 app:layout_scrollFlags=”scroll|enterAlways” 屬性。
          給你的可滑動的組件,也就是RecyclerView 或者 NestedScrollView、ListView,ScrollView等設(shè)置如下屬性:
           app:layout_behavior="@string/appbar_scrolling_view_behavior"-->


    <!--默認(rèn)的AppBarLayout是垂直方向的,它的作用是把AppBarLayout包裹的內(nèi)容都作為AppBar
        此處將Toolbar 和Tablayout的組合部分共同構(gòu)成 AppBar的效果。
        注意: AppBarLayout必須作為Toolbar的父布局容器;
        AppBarLayout是支持手勢滑動效果的,不過的跟CoordinatorLayout配合使用;-->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <!--設(shè)置的layout_scrollFlags有如下幾種選項:
             scroll: 所有想滾動出屏幕的view都需要設(shè)置這個flag- 沒有設(shè)置這個flag的view將被固定在屏幕頂部。
             enterAlways: 這個flag讓任意向下的滾動都會導(dǎo)致該view變?yōu)榭梢?,啟用快速“返回模式”?             enterAlwaysCollapsed: 當(dāng)你的視圖已經(jīng)設(shè)置minHeight屬性又使用此標(biāo)志時,你的視圖只能已最小高度進入,只有當(dāng)滾動視圖到達(dá)頂部時才擴大到完整高度。
             exitUntilCollapsed: 滾動退出屏幕,最后折疊在頂端。-->
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            app:tabIndicatorColor="@color/white"
            app:tabSelectedTextColor="@color/gray"
            app:tabTextColor="@color/white"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

圖中我的實例中頭部有三個布局:

<android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#66ffffff"
        app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:expandedTitleMarginStart="48dp"
            android:background="@mipmap/rectangle"
            app:expandedTitleMarginEnd="64dp">
            <android.support.design.widget.TabLayout
                android:id="@+id/tab"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:tabTextColor="#ffffff"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.8"
                android:layout_marginTop="120dp"
                android:paddingBottom="15dp"
                />
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:contentInsetLeft="0dp"
                app:contentInsetStart="0dp"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin">
                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
                    <LinearLayout
                        android:id="@+id/toolbar1"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent">
                        <TextView
                            android:id="@+id/layout1_tv"
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:gravity="center"
                            android:text="布局一"
                            android:textColor="#ffffff"
                            android:textSize="20sp"/>
                    </LinearLayout>
                    <LinearLayout
                        android:id="@+id/toolbar2"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:orientation="horizontal"
                        android:visibility="gone">
                        <TextView
                            android:id="@+id/layout2_tv1"
                            android:layout_width="wrap_content"
                            android:layout_height="match_parent"
                            android:gravity="center"
                            android:text="布局二"
                            android:textColor="#ffffff"
                            android:textSize="20sp"/>
                        <TextView
                            android:id="@+id/layout2_tv2"
                            android:layout_width="wrap_content"
                            android:layout_height="match_parent"
                            android:gravity="center"
                            android:text="布局二"
                            android:layout_marginLeft="20dp"
                            android:textColor="#ffffff"
                            android:textSize="20sp"/>
                    </LinearLayout>
                </RelativeLayout>
            </android.support.v7.widget.Toolbar>

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

TabLayout中的第三個布局是我需要實現(xiàn)滑動效果的

布局三

設(shè)置的layout_scrollFlags有如下幾種選項:

  • scroll: 所有想滾動出屏幕的view都需要設(shè)置這個flag- 沒有設(shè)置這個flag的view將被固定在屏幕頂部。
  • enterAlways: 這個flag讓任意向下的滾動都會導(dǎo)致該view變?yōu)榭梢姡瑔⒂每焖佟胺祷啬J健薄?/li>
  • enterAlwaysCollapsed: 當(dāng)你的視圖已經(jīng)設(shè)置minHeight屬性又使用此標(biāo)志時,你的視圖只能已最小高度進入,只有當(dāng)滾動視圖到達(dá)頂部時才擴大到完整高度。
  • exitUntilCollapsed: 滾動退出屏幕,最后折疊在頂端。

接著基本頭部布局設(shè)置完成,需要完成的是頭部滑動完成以后,布局一和布局二的顯隱。我們實現(xiàn)Appbarlayout的addOnOffsetChangedListener監(jiān)聽:

/** appbarLayout **/
        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if(verticalOffset == 0){
                    view1.setVisibility(View.VISIBLE);
                    view2.setVisibility(View.GONE);
                    //alpha 變化
                    setToolbar1Alpha(255);

                }else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()){
                    view1.setVisibility(View.GONE);
                    view2.setVisibility(View.VISIBLE);
                    //alpha 變化
                    setToolbar2Alpha(255);
                }else{
                    int alpha=255-Math.abs(verticalOffset);
                    if(alpha<0){
                        //收縮toolbar
                        view1.setVisibility(View.GONE);
                        view2.setVisibility(View.VISIBLE);
                        setToolbar2Alpha(Math.abs(verticalOffset));
                    }else{
                        //張開toolbar
                        view1.setVisibility(View.VISIBLE);
                        view2.setVisibility(View.GONE);
                        setToolbar1Alpha(alpha);
                    }
                }
            }
        });

布局是圖片的話,alpha變化就會有了。

項目地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,769評論 25 709
  • CoordinatorLayout與滾動的處理 CoordinatorLayout實現(xiàn)了多種Material De...
    cxm11閱讀 6,799評論 1 15
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點贊按鈕進度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 47,133評論 22 665
  • 有人說,婚姻是愛情的墳?zāi)埂?蓻]了婚姻的愛情,愛情就沒了葬身之所。 我這里并非是擇其中之一更重要,而是若愛情一開始就...
    曉妮臆空間閱讀 981評論 0 0

友情鏈接更多精彩內(nèi)容