1. 程式人生 > >CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout+NestedScrollView實現上下滑動懸停效果

CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout+NestedScrollView實現上下滑動懸停效果

這張圖解析上面幾個控制元件的關係: 

轉載:https://www.jianshu.com/p/1f3974408528   CoordinatorLayout配合AppBarLayout、CollapsingToolbarLayout、Toolbar使用

轉載:https://blog.csdn.net/feather_wch/article/details/80021699   

載:https://www.jianshu.com/p/f09723b7e887/  使用CoordinatorLayout打造各種炫酷的效果

精華文章:https://blog.csdn.net/a_yue10/article/details/78653805

 一句程式碼解決CoordinatorLayout+AppBarLayout+NestedScrollView滑動不流暢的問題

 

先認識以下控制元件及屬性

1、匯入包://根據自己的模擬器版本

    implementation 'com.android.support:design:26.1.0'

2、CoordinatorLayout的作用

  1. 加強版FrameLayout,適合作為應用頂層的佈局(必須是根部局),提供互動行為
  2. 通過給子View設定Behavior可以實現他們的互動性為。Behavior能實現一系列的互動行為和佈局變化,包括側滑選單
    可滑動刪除的UI元素View之間跟隨移動
  3. 常用支援滑動效果的子View有:比如RecyclerView,NestedScrollView、TabLayout等    ScrollView是無效的!!

 3、CoordinatorLayout的Behavoir 觀察者

佈局: 需要給觀察者設定Behavoir(一般搭配使用的RecyclerViewNestedScrollView、TabLayout都可以是它的觀察者

AppBarLayout

8、AppBarLayout是什麼  

  • 是一個vertical的LinearLayout,其子View應通過setScrollFlags(int)或者xmL中的app:layout_scrollFlags來提供他們的Behavior。
  • 具體的app:layout_scrollFlags有這麼幾個: scroll, exitUntilCollapsed, enterAlways, enterAlwaysCollapsed, snap
  • 他必須嚴格地是CoordinatorLayout的子View,不然他一點作用都發揮不出來。
  • AppBarLayout下方的滑動控制元件,比如RecyclerView,NestedScrollView(與AppBarLayout同屬於CoordinatorLayout的子View,並列的關係,),必須嚴格地通過在xml中指出其滑動Behavior來與AppBarLayout進行繫結。
  • 通常這樣:app:layout_behavior="@string/appbar_scrolling_view_behavior"

Toolbar:

  • 他的title如果需要帶有CollapsingToolbarLayout的動畫的話,就要用collapsingToolbarLayout.setTitle(); 否則是沒有動畫的,其他的和toolbar平時一樣。

9、app:layout_scrollFlags的具體引數

引數 作用
scroll -值設為scroll的View會跟隨滾動事件(可以滾動的View)一起發生移動
EnterAlways -實現quick return效果, 當向下移動時,立即顯示View(比如Toolbar)。
ExitUntilCollapsed - 向上滾動時收縮View,但可以固定Toolbar一直在上面。
EnterAlwaysCollapsed 當你的View已經設定minHeight屬性又使用此標誌時,你的View只能以最小高度進入,只有當滾動檢視到達頂部時才擴大到完整高度。
snap “觀察者-標題欄”要麼完全出現,要麼完全為0 (同時出現,同時回收)

其中還設定了一些屬性,簡要說明一下:
contentScrim - 設定當完全CollapsingToolbarLayout摺疊(收縮)後的背景顏色。(不設定就不會有淡出淡入的效果)

expandedTitleMarginStart - 設定擴張時候(還沒有收縮時)title向左填充的距離。

10、AppBarLayout的聯動使用例項 

  1. CoordinatorLayout包裹著一個AppBarLayout和一個Scrolling View(RV等等)
  2. AppBarLayout內部控制元件需要指明scrollFlags
  3. Scrolling View需要指定layout_behavior
<android.support.design.widget.CoordinatorLayout
  xxx>

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbarlayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.TabLayout
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:background="#00A999"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlwaysCollapsed|snap"/>
    </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:layout_behavior="@string/appbar_scrolling_view_behavior">
    </android.support.v7.widget.RecyclerView>
</android.support.design.widget.CoordinatorLayout>

 11、AppBarLayout展開和摺疊的狀態判斷

//監聽是展開還是摺疊
mAppBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
    @Override
    public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
        if(verticalOffset == 0){
            //完全展開狀態
        }else if(Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()){
            //摺疊狀態
        }else{
            //中間狀態
        }
    }
});

CollapsingToolBarLayout

  • 是一個專門用來包裹Toolbar的控制元件,裡面可以放置一個imageView和一個toolbar然後輕鬆地實現:隨著滑動,圖片和toolbar的標題也有動畫。
  • 內部的子View一般都要加上屬性:app:layout_collapseMode="",常用的是parallax,pin。parallax是視差滾動,用在imageView, pin是固定,用在toolbar。
  • setContentScrimColor(int)或者setContentScrim(drawable)來設定內容紗布,就是當摺疊到只剩下Toolbar的時候,用一個另外的圖片或者顏色來設定toolbar的背景。
  1. 用於實現具有摺疊效果的頂部欄
  2. CollapsingToolBarLayout必須是AppBarLayout的直接子View

13、CollapsingToolBarLayout包含的特性

特性  
Collapsing title(可摺疊標題)    佈局完全可見時,標題比較大;佈局摺疊起來時,標題會變小。外觀可以通過expandedTextAppearance和collapsedTextAppearance屬性調整。
contentScrim(內容抹布)  如果滾動到臨界點,內容麻布會顯示或者隱藏。setContentScrim(Drawable)設定抹布內容。
Status bar Scrim(狀態列紗布)   設定當完全CollapsingToolbarLayout摺疊(收縮)後的背景顏色。
app:layout_collapseMode(視差滾動) parallax,pin。parallax

14、CollapsingToolbarLayout的重要屬性

/**======================
 * 自身屬性
 *======================*/
# 紗布
app:contentScrim="?attr/colorPrimary" //完全摺疊後的背景色
app:scrimAnimationDuration="1000"     //紗布動畫持續時間
app:scrimVisibleHeightTrigger="20dp"  //紗布可見的最小距離(低於就會開始隱身)

# 狀態列紗布(下面會特別介紹)
app:statusBarScrim="@color/colorAccent"

# 標題
app:title="Hello"             //標題優先於"ToolBar標題Title"
app:titleEnabled="true"       //是否使用大標題,true-使用;false-不使用

app:expandedTitleMargin="1dp" //"自身Title"或者"ToolBar標題Title"的Margin值
app:expandedTitleMarginStart="1dp"
app:expandedTitleMarginEnd="1dp"
app:expandedTitleMarginTop="1dp"
app:expandedTitleMarginBottom="1dp"
app:expandedTitleTextAppearance="?attr/cardBackgroundColor"

app:expandedTitleGravity="bottom|center_horizontal" //"ToolBar標題Title"的重力

# 摺疊後Title的重力和樣式
app:collapsedTitleGravity="center_horizontal"
app:collapsedTitleTextAppearance="?attr/colorAccent"

# 需要參考AppBarLayout的`app:layout_scrollFlags`
app:layout_scrollFlags=“xxxx”

# 指明toolbar的ID
app:toolbarId="@id/stars_toolbar"

 一般是Toolbar放在頂部固定不動

/**======================
 * 內部控制元件的屬性
 *======================*/
# 視差(以ParallaxMultiplier的速度摺疊,0:最慢~1:最快)
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5"

# 摺疊後會固定在頂部
app:layout_collapseMode="pin"

15、狀態列紗布(statusBarScrim)如何生效?

CollapsingToolBarLayout設定app:statusBarScrim="@color/colorAccent"

給父容器AppBarLayout設定屬性android:fitsSystemWindows="true",防止狀態列透明後出現標題欄移位到狀態列的錯誤。

通過下面三種方法之一將狀態列設定為全透明

1.在style.xml中增加下面的程式碼把狀態列設定成全透明

 <item name="android:statusBarColor">@android:color/transparent</item>

2.在style.xml中增加下面的程式碼把狀態列設定成半透明

 <item name="android:windowTranslucentStatus">true</item>

3.在java程式碼中onCreate()方法裡把狀態列設定成半透明

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

補充:如果你已經在style裡面把狀態列設定成了透明,那麼CollapsingToolbarLayout也想要透明效果的話就無需設定了。

16、FloatingActionButton的屬性以及CoordinatorLayout中的錨點屬性

# 參考的錨點 app:layout_anchor=”@id/appbar”

# 與錨點的位置關係 app:layout_anchorGravity=”end|bottom|right”

17、程式碼設定CollapsingToolbarLayout標題顏色

//1. 展開時標題顏色
mCollapsingToolbarLayout.setExpandedTitleColor(Color.BLACK);
//2. 摺疊時標題顏色
mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.WHITE);

 

參考資料

  1. CollapsingToolBarLayout用法
  2. 利用 CollapsingToolbarLayout 完成聯動的動畫效果
  3. CollapsingToolbarLayout 收縮時狀態列顏色設定不生效

程式碼:

xml檔案

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:id="@+id/collapsingToolbar"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            android:layout_height="wrap_content">
            <ImageView
                android:scaleType="centerCrop"
                android:src="@drawable/beauty"
                android:layout_width="match_parent"
                app:layout_collapseMode="parallax"
                android:layout_height="300dp" />
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                app:layout_collapseMode="pin"
                android:layout_width="match_parent"
                android:minHeight="?attr/actionBarSize"
                android:layout_height="?attr/actionBarSize">

            </android.support.v7.widget.Toolbar>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"

        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_height="wrap_content">
        <TextView
            android:text="@string/textContent"
            android:textSize="20sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </android.support.v4.widget.NestedScrollView>

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

 

MainActivity:

public class MainActivity extends AppCompatActivity {
    Toolbar toolbar;
    CollapsingToolbarLayout collapsingToolbarLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.coordinatory_layout);
        //toolbar
        toolbar = findViewById(R.id.toolbar);
        toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
        //Palette用來更漂亮地展示配色
        Palette.from(BitmapFactory.decodeResource(getResources(),R.drawable.beauty))
                .generate(new Palette.PaletteAsyncListener() {
                    @Override
                    public void onGenerated(@NonNull Palette palette) {
                        int color=palette.getVibrantColor(getResources().getColor(R.color.colorAccent));
                        collapsingToolbarLayout.setContentScrimColor(color);
                        //因為我暫時沒有找到比較好的透明狀態列來適配這一套效果佈局。
                        //因此就直接替換掉StatusBar的顏色,這樣其實也蠻好看的。
                        getWindow().setStatusBarColor(color);
                    }
                });
        //CollapsingToolbarLayout
        collapsingToolbarLayout = findViewById(R.id.collapsingToolbar);
        collapsingToolbarLayout.setTitle("我是一個標題啊哈哈哈");
    }
}

下面是我自己的效果:

<?xml version="1.0" encoding="utf-8"?><!--
1.CoordinatorLayout 根部局
2.CollapsingToolbarLayout
(1.自身設定falg來進行滑動效果)
(2.新增一個Toolbar控制元件設定頂部標題欄不動)

3.NestedScrollView (提供滑動scroll的行為behivor)
當進行滑動時,設定有flag的佈局就會隨機滑動
-->
<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:orientation="vertical"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar">

        <!--app:contentScrim當完全收縮後的背景色-->
        <!--不設定這個屬性,就沒有淡入淡出的效果了-->
        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:contentScrim="?attr/colorPrimary"
            app:collapsedTitleTextAppearance="@style/TextAppearance.AppCompat.Title"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|enterAlwaysCollapsed"
            app:titleEnabled="false">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="60dp"
                android:layout_marginTop="50dp">

                <EditText
                    android:id="@+id/id_add_note_title_et"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"
                    android:background="@null"
                    android:hint="標題"
                    android:minHeight="10dp"
                    android:textSize="30dp"
                    android:textStyle="bold" />

            </LinearLayout>


            <!--toolbar設定pin屬性後,Toolbar還可以保留在螢幕上-->

            <android.support.v7.widget.Toolbar
                android:id="@+id/id_add_note_title_layout"
                android:layout_width="match_parent"
                android:layout_height="55dp"
                android:background="#fff"
                app:contentInsetStart="0dp"
                app:layout_collapseMode="pin"
                app:title="@null">

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical">


                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="48dp"
                        android:orientation="horizontal">

                        <LinearLayout
                            android:layout_width="50dp"
                            android:layout_height="match_parent"
                            android:gravity="left">

                            <ImageView
                                android:id="@+id/id_add_note_back"
                                android:layout_width="30dp"
                                android:layout_height="30dp"
                                android:layout_gravity="center_vertical"
                                android:layout_margin="10dp"
                                android:background="@drawable/left_circle"
                                android:onClick="back" />

                        </LinearLayout>

                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="match_parent"
                            android:gravity="right">

                            <ImageView
                                android:id="@+id/id_note_delete_iv"
                                android:layout_width="30dp"
                                android:layout_height="30dp"
                                android:layout_margin="10dp"
                                android:background="@drawable/delete_btn"
                                android:onClick="deleteNote" />


                        </LinearLayout>

                    </LinearLayout>

                    <View
                        android:layout_width="match_parent"
                        android:layout_height="1dp"
                        android:background="#969191"

                        />
                </LinearLayout>
            </android.support.v7.widget.Toolbar>


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


<!--下劃線-->
        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginEnd="10dp"
            android:layout_marginStart="10dp"
            android:background="#969191" />


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


<!--滑動的行為者 app:layout_behavior 預設的-->


    <android.support.v4.widget.NestedScrollView
        android:id="@+id/id_add_note_scroll"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">


        <EditText
            android:id="@+id/id_add_note_content_et"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:background="@null"
            android:gravity="top"
            android:hint="內容"
            android:minLines="10"
            android:textSize="20dp" />

    </android.support.v4.widget.NestedScrollView>

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

大家一起學習。。。。