AppBarLayout的七種scrollFlags


1、前言

查看 Android 文檔下,com.google.android.material.appbar 包下的 AppBarLayout.LayoutParams 類有一個 AppBarLayout_layout_layout_scrollFlags 屬性,這個屬性可以有七種取值:
 
這些取值在 xml 里也有對應的值:
我們發現只有六個值,缺少的一個是 noScroll,這個值是默認缺省值,在不使用 app:layout_scrollFlags 屬性的時候,就是 noScroll 效果。
 

2、正文

2、1、准備工作

在介紹之前,需要有一個小例子,效果是這樣的:
 
最上邊的我的標題部分是一個 Toolbar,Tab 區域是 TabLayout,這兩者在 AppBarLayout 布局里面,因為 AppBarLayout 本身是一個 vertical 布局的LinearLayout,所以 Toolbar 和 TabLayout 是豎向排列的。然后,下邊是一個 ViewPager 布局,切換三個 Fragment,每個 Fragment
又是一個 RecyclerView 列表布局。我們打算把layout_scrollFlags 添加到 Toolbar 節點下來演示 layout_scrollFlags 的七種取值的效果。
對應的 xml 布局如下:
<?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"
    tools:context=".MainActivity">

    <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"
            app:title="我的標題" />

        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabTextAppearance="@style/CustomStyle.TabLayoutTextStyle" />

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

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <!-- Your scrolling content -->
        <androidx.viewpager.widget.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
 

2.2、noScroll

Disable scrolling on the view. This flag should not be combined with any of the other scroll flags.

Constant Value: 0 (0x00000000)

禁用視圖上的滾動。此標志不應與任何其他滾動標志相結合。

常數值:0 (0x00000000)
 
在沒有添加任何 layout_scrollFlags 時,AppBarLayout 的子 View 是沒有滾動效果的。這等價於添加了app:layout_scrollFlags="noScroll"(其實如果添加了是會報錯的,所以這個效果就不添加好了),如下:
<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolBar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:title="我的標題" />
 
運行效果如下:
 

 2.3、scroll

The view will be scroll in direct relation to scroll events. 
This flag needs to be set for any of the other flags to take effect.
If any sibling views before this one do not have this flag, then this value has no effect. Constant Value: 1 (0x00000001)
視圖將與滾動事件直接相關。
需要設置此標志才能使其他任何標志生效。
如果此視圖之前的任何同級視圖沒有此標志,則此值無效。

這個文檔解釋的內容比較多。我們一一來演示。首先在 Toolbar 下添加這個 flag

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolBar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    app:layout_scrollFlags="scroll"
    app:title="我的標題" />
運行效果如下,可以看到 Toolbar 可以隨着滾動事件而滾動:

 現在我們把 app:layout_scrollFlags="scroll" 挪到 TabLayout 上,同時將 Toolbar 上的該屬性刪除:

<androidx.appcompat.widget.Toolbar
      android:id="@+id/toolBar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      app:title="我的標題" />
      
<com.google.android.material.tabs.TabLayout
      android:id="@+id/tabLayout"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:layout_scrollFlags="scroll"
      app:tabTextAppearance="@style/CustomStyle.TabLayoutTextStyle" />

 運行效果如下:

可以看到和沒有設置任何 layout_scrollFlags 的效果是一模一樣的。這是怎么回事呢?

看一下前面的文檔說明:如果此視圖之前的任何同級視圖沒有此標志,則此值無效。
因為我們在 TabLayout 上面設置了 app:layout_scrollFlags="scroll",而位於 TabLayout 之前的 Toolbar 沒有設置 app:layout_scrollFlags="scroll",所以 TabLayout 設置的 app:layout_scrollFlags="scroll" 失效了。
 
那么怎么才能有效果呢?
在 Toolbar 上也設置 app:layout_scrollFlags="scroll"。運行效果如下:
可以看到 Toolbar 和 TabLayout 一起都隨着滾動事件而滾動了。

2.4、enterAlways

When entering (scrolling on screen) the view will scroll on any downwards scroll event, regardless of whether the scrolling view is also scrolling. 
This is commonly referred to as the 'quick return' pattern. Constant Value: 4 (0x00000004)

當進入(即在屏幕上的滾動手指由上向下滑動)時,設置了這個 flag 的 View一遇到向下的滾動事件就會滾動,不管滾動的 View是否也在滾動中。這通常被稱為“快速返回”模式。

 
修改 Toolbar 的 layout_scrollFlags 屬性如下:
<androidx.appcompat.widget.Toolbar
      android:id="@+id/toolBar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      app:layout_scrollFlags="scroll|enterAlways"
      app:title="我的標題" />

運行效果如下:

 和上面單獨設置 scroll 的效果相比,在滾出屏幕時的效果是一樣的,不同的地方在於滾入屏幕時:scroll 先滾動 Scrolling View,再滾動設置 flag 的View(即 Toolbar);scroll|enterAlways 先滾動設置 flag 的 View(即 Toolbar),再滾動 Scrolling View。

2.5、enterAlwaysCollapsed

An additional flag for 'enterAlways' which modifies the returning view to only initially scroll back to it's collapsed height. 
Once the scrolling view has reached the end of it's scroll range, the remainder of this view will be scrolled into view. 
The collapsed height is defined by the view's minimum height.

Constant Value: 8 (0x00000008)

這是 ‘enterAlways’ 的一個附加的 flag。作用是修改返回的 View 的進入效果。首先,返回的 View 會滾動返回到它的折疊高度。當滾動的 View一達到它的滾動范圍的末尾時,返回的View還在視圖外的部分就會滾動進入視圖。折疊高度是通過返回的View的最小高度來定義的。

可以看到額外添加這個 flag,是把進入過程分開走,首先Toolbar會滾動到折疊的高度,等列表滾動到末尾時,Toolbar的剩余部分才會滾動進入視圖。
修改 xml 如下,記得添加 minHeight 屬性:
<androidx.appcompat.widget.Toolbar
      android:id="@+id/toolBar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      android:minHeight="20dp"
      app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
      app:title="我的標題" />
運行效果如下:
 

 2.6、exitUntilCollapsed

When exiting (scrolling off screen) the view will be scrolled until it is 'collapsed'. 
The collapsed height is defined by the view's minimum height.

Constant Value: 2 (0x00000002)
當退出(即手指在屏幕上由下向上滑動)時,設置這個 flag 的 View 會滾動直至它的折疊高度。
折疊高度是由這個View的最小高度來定義的。
這個 flag 關注的是退出過程。 修改 xml 代碼如下:
<androidx.appcompat.widget.Toolbar
      android:id="@+id/toolBar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      android:minHeight="20dp"
      app:layout_scrollFlags="scroll|exitUntilCollapsed"
      app:title="我的標題" />

 運行效果如下:

2.7、snap

Upon a scroll ending, if the view is only partially visible then it will be snapped and scrolled to its closest edge. 
For example, if the view only has its bottom 25% displayed, it will be scrolled off screen completely. 
Conversely, if its bottom 75% is visible then it will be scrolled fully into view.

Constant Value: 16 (0x00000010)
滾動一結束,如果這個 View 僅僅部分可見那么它就會被 snapped 並滾動到它最近的邊緣。例如,如果這個 View 僅有底部的 25% 部分可見,那么它就會完全地滾出屏幕。相反,如果它有底部的 75% 部分可見,那么它就會全部滾入屏幕。
 
關於 snap 這個單詞的理解,有人翻譯成吸附效果。我查了一下詞典,覺得這個意思比較貼切:
 
修改 xml,如下:
<androidx.appcompat.widget.Toolbar
      android:id="@+id/toolBar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      app:layout_scrollFlags="scroll|snap"
      app:title="我的標題" />

 運行效果如下:

2.8、snapMargins

An additional flag to be used with 'snap'. 
If set, the view will be snapped to its top and bottom margins, as opposed to the edges of the view itself.

Constant Value: 32 (0x00000020)

這是和 ‘snap’ 一起使用的額外的 flag。

如果設置的話,這個 View 將會被 snap 到它的頂部外邊距和它的底部外邊距的位置,而不是這個 View 自身的上下邊緣。

 

修改 xml,如下:

<androidx.appcompat.widget.Toolbar
      android:id="@+id/toolBar"
      android:layout_width="match_parent"
      android:layout_height="?attr/actionBarSize"
      android:layout_marginTop="20dp"
      android:layout_marginBottom="20dp"
      app:layout_scrollFlags="scroll|snap|snapMargins"
      app:title="我的標題" />

 運行效果如下:

 

傳送門:https://github.com/First-Time/ScrollFlagsDemo    (Kotlin)

    https://github.com/First-Time/ScrollFlagsJavaDemo (Java)

 

參考

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM