Android 中 CoordinatorLayout + AppBarLayout 實現滑動頭部懸停效果(頁面附帶TabLayout + ViewPager + RecyclerView結構)

昨晚經歷了美股本月的第三次熔斷 ,有史以來的第四次熔斷 。

突 。 突突 。。突突突 。。。

 

 

很尷尬 ,找不到做 gif 的東西 。怎麼辦呢 。(找了好久 ,在手機上下載了一個  GIF 動圖製作)

效果如下

 

AppbarLayout 回顧

我記得 16 、17年的時候這個效果在很多 APP 上都有出現 。之前寫過demo ,然後一直也沒機會在項目中使用 。

 

實現類似的效果 ,主要是使用三個控件相結合 CoordinatorLayout 、AppbarLayout 、NestedScrollView 。

AppbarLayout 是一種支持響應滾動手勢的 app bar 佈局 , CollapsingToolbarLayout 則是專門用來實現子佈局內不同元素響應滾動細節的佈局 。與 AppbarLayout 組合的滾動佈局 (RecyclerView, NestedScrollView等) , 需要設置 app:layout_behavior = "@strng/appbar_scrolling_view_behavior" 。 沒有設置的話 , AppbarLayout 將不會響應滾動佈局的滾動事件 。

 

簡單的效果代碼

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
    >
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:layout_scrollFlags="scroll"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:title="Title" />
    </com.google.android.material.appbar.AppBarLayout>
    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <TextView
            android:id="@+id/tv_content"
            android:layout_margin="16dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:lineSpacingMultiplier="2"
            />
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

效果如下

效果如下
 

  • 隨着文本往上滾動, 頂部的toolbar也往上滾動, 直到消失.
  • 隨着文本往下滾動, 一直滾到文本的第一行露出來, toolbar也逐漸露出來

 

AppBarLayout 繼承自LinearLayout,佈局方向爲垂直方向。所以你可以把它當成垂直佈局的LinearLayout來使用。AppBarLayout是在LinearLayou上加了一些材料設計的概念,它可以讓你定製當某個可滾動View的滾動手勢發生變化時,其內部的子View實現何種動作。
 

 

我們可以通過給Appbar下的子View添加app:layout_scrollFlags來設置各子View執行的動作. scrollFlags可以設置的動作如下:

  • scroll: 值設爲scroll的View會跟隨滾動事件一起發生移動。就是當指定的ScrollView發生滾動時,該View也跟隨一起滾動,就好像這個View也是屬於這個ScrollView一樣。
  • enterAlways: 值設爲enterAlways的View,當任何時候ScrollView往下滾動時,該View會直接往下滾動。而不用考慮ScrollView是否在滾動到最頂部還是哪裏.
  • exitUntilCollapsed:值設爲exitUntilCollapsed的View,當這個View要往上逐漸“消逝”時,會一直往上滑動,直到剩下的的高度達到它的最小高度後,再響應ScrollView的內部滑動事件。
  • enterAlwaysCollapsed:是enterAlways的附加選項,一般跟enterAlways一起使用,它是指,View在往下“出現”的時候,首先是enterAlways效果,當View的高度達到最小高度時,View就暫時不去往下滾動,直到ScrollView滑動到頂部不再滑動時,View再繼續往下滑動,直到滑到View的頂部結束 。

參考 :https://www.jianshu.com/p/bbc703a0015e

PS:更多的細節可以查看文章鏈接 。

 

實現項目效果

可以回到文章頂部在看一下項目要求的效果 。

頂部是四個 Tab ,下面是 ViewPager + Fragment + RecyclerView 。如果在加上懸浮效果的話 ,那這個頁面結構是 CoordinatorLayout + AppBarLayout + TabLayout + ViewPager + Fragment + RecyclerView 。

 

1. XML 佈局

<LinearLayout 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:background="@color/white"
    android:orientation="vertical">

    <include layout="@layout/actionbar_title_back" />


    <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:orientation="vertical">

        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            app:elevation="0dp">


            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="@dimen/dp_56"
                app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

                <ImageView
                    android:id="@+id/iv_image"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_128"
                    android:scaleType="centerCrop"
                    android:src="@drawable/bg_classroom_tab"
                    app:layout_constraintTop_toTopOf="parent" />


                <net.lucode.hackware.magicindicator.MagicIndicator
                    android:id="@+id/magic_indicator"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/dp_106"
                    android:layout_marginTop="@dimen/dp_10"
                    app:layout_constraintTop_toTopOf="parent" />

            </androidx.constraintlayout.widget.ConstraintLayout>


        </com.google.android.material.appbar.AppBarLayout>


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

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</LinearLayout>

可以看到 AppBarLayout 裏面包含的佈局是 ConstraintLayout 。

PS :一定要設置 ConstraintLayout 的 app:layout_scrollFlags="scroll|exitUntilCollapsed|snap" 屬性 。 **

PS1: ConstraintLayout 一定要給個 android:minHeight="@dimen/dp_56" 最小高度 。 **

(可以自己多設置幾次 ,感受一下其中的變化)

 

接下來就是ViewPager 的 layout_behavior 屬性 。

PS:一定要設置 ,負責會覆蓋佈局 。

 

 

 

難點應該是 ConstraintLayout 的 app:layout_scrollFlags 屬性和 android:minHeight 屬性 。

 

 

 

 

 

代碼已經上傳到 Github 。SuperTest

demo 項目裏面的路徑 首頁 —— 點擊下方的 RXJAVA按鈕 ——  點擊懸浮效果按鈕 。

可以搜下面代碼

 case R.id.collapsing:
                intent2Activity(CollapsingActivity.class);
                break;

 

PS:SuperTest 是一個很大的 demo 項目 。SuperTest 項目使用框架是 Supermax (可以 Look Look )。

 

 

 

 

PS:如果有什麼問題,歡迎文章下面補充 。

 

 

微信公衆號:SuperMaxs

如果感覺文章對您有幫助 ,可以關注我的公衆號 SuperMaxs (如果有技術問題可以通過公衆號加私人微信)。

 

星球瞭解:https://t.zsxq.com/yJ2fq3z

 

 



 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章