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)

 

参考

 

posted @ 2020-05-14 15:38  第壹时间  阅读(3604)  评论(0编辑  收藏  举报