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



 

发布了70 篇原创文章 · 获赞 56 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_37492806/article/details/104926969