Android 仿支付宝首页头部伸缩效果及相关控件CoordinatorLayout、AppBarLayout、CollapsingToolbarLayout的使用介绍

首先看效果图:


preview.gif

gradle 关联

implementation 'com.google.android.material:material:1.0.0'

下面介绍示例用到的几个布局:

CoordinatorLayout

CoordinatorLayout 是一个 “加强版” FrameLayout, 它主要有两个用途:

  • 用作应用的顶层布局管理器,也就是作为用户界面中所有 UI 控件的容器;
  • 用作相互之间具有特定交互行为的 UI 控件的容器,通过为 CoordinatorLayout 的子 View 指定 Behavior, 就可以实现它们之间的交互行为。 Behavior 可以用来实现一系列的交互行为和布局变化,比如说侧滑菜单、可滑动删除的 UI 元素,以及跟随着其他 UI 控件移动的按钮等。

AppBarLayout

实际上我们在应用中有 CoordinatorLayout 的地方通常都会有 AppBarLayout 的联用。

AppBarLayout 是一个垂直的 LinearLayout,实现了 Material Design 中 App bar 的 Scrolling Gestures 特性。AppBarLayout 的子 View 应该声明想要具有的“滚动行为”,这可以通过 layout_scrollFlags 属性或是 setScrollFlags() 方法来指定。

AppBarLayout 只有作为 CoordinatorLayout 的直接子 View 时才能正常工作,为了让 AppBarLayout 能够知道何时滚动其子 View,我们还应该在 CoordinatorLayout 布局中提供一个可滚动 View,我们称之为 Scrolling View。

Scrolling View 和 AppBarLayout 之间的关联,通过将 Scrolling View 的 Behavior 设为 AppBarLayout.ScrollingViewBehavior 来建立。

AppBarLayout 主要给子布局配置属性 app:layout_scrollFlags,layout_scrollFlags 的取值可以为以下几种。

  • scroll:设置滚动效果,没有设置这个属性的view将被固定在屏幕顶部
  • enterAlways:与 scroll 类似(scroll|enterAlways),只不过向下滚动先显示 AppBarLayout 到完全,再滚动 Scrolling View
  • enterAlwaysCollapsed:需要和 enterAlways 一起使用(scroll|enterAlways|enterAlwaysCollapsed),和 enterAlways 不一样的是,不会显示 AppBarLayout 到完全再滚动 Scrolling View,而是先滚动 AppBarLayout 到最小高度,再滚动 Scrolling View,最后再滚动 AppBarLayout 到完全显示。
    注意:需要定义 View 的最小高度(minHeight)才有效果:
    android:minHeight="10dp"
    app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
    
  • exitUntilCollapsed:当本 View 离开屏幕时,会被“折叠”直到达到其最小高度。我们可以这样理解这个效果:当我们开始向上滚动 Scrolling view 时,本 View 会先接管滚动事件,这样本 View 会先进行滚动,直到滚动到了最小高度(折叠了),Scrolling view 才开始实际滚动。而当本 View 已完全折叠后,再向下滚动 Scrolling view,直到 Scrolling view 顶部的内容完全显示后,本 View 才会开始向下滚动以显现出来。
    android:minHeight="10dp"
    app:layout_scrollFlags="scroll|exitUntilCollapsed"
    
  • snap:在一次滚动结束时,本 View 很可能只处于“部分显示”的状态,加上这个标记能够达到“要么完全隐藏,要么完全显示”的效果。例如,如果视图只有底部25%显示,它将折叠。相反,如果它的底部75%可见,那么它将完全展开。

CollapsingToolbarLayout

CollapsingToolbarLayout 继承自 FrameLayout,它是用来实现 Toolbar 的折叠效果,一般它的直接子 View 是 Toolbar,当然也可以是其它类型的 View。

collapsingToolbarLayout 可以作为 AppBarLayout 的子 view,可以控制包含在其中的控件在滚动时的响应事件,子 view 可以是个可折叠的 Toolbar,app:layout_collapseMode 设置折叠模式。

CollapsingToolbarLayout 常用xml属性介绍

  • contentScrim:当Toolbar收缩到一定程度时的所展现的主体颜色。即Toolbar的颜色。
  • title:当titleEnable设置为true的时候,在toolbar展开的时候,显示大标题,toolbar收缩时,显示为toolbar上面的小标题。
  • scrimAnimationDuration:该属性控制 toolbar 收缩时,颜色变化的动画持续时间。即颜色变为 contentScrim 所指定的颜色进行的动画所需要的时间。
  • expandedTitleGravity:指定 toolbar 展开时,title 所在的位置。类似的还有expandedTitleMargin、collapsedTitleGravity 这些属性。
  • collapsedTitleTextAppearance:指定 toolbar 收缩时,标题字体的样式,类似的还有 expandedTitleTextAppearance。

app:layout_collapseMode 折叠模式:

  • pin:折叠后,此布局将固定在顶部。
  • parallax:折叠时,此布局也会有视差折叠效果。
    当其子布局设置了parallax模式时,我们还可以通过app:layout_collapseParallaxMultiplier 设置视差滚动因子,值为:0~1。

实现过程

1、 coordinatorLayout 嵌套 appBarLayout 。
2、appBarLayout 的子 view collapsingToolbarLayout 设置属性app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
让头部随着内容下拉而展开,随着内容上拉而收缩。
3、collapsingToolbarLayout 的子布局有两种,展开时显示的布局和 Toolbar,其中 Toolbar 又包含了两种布局,展开时的和收缩时的。 展开时,(扫一扫、付钱)的布局:

<include
    layout="@layout/include_open"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="50dp"
    app:layout_collapseMode="parallax"
    app:layout_collapseParallaxMultiplier="0.7" />

layout_marginTop="50dp" 预留出 toolbar 的高度,避免布局重叠。

toolbar里的两种布局:

<!--pin:折叠后,此布局将固定在顶部。   -->
<androidx.appcompat.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="50dp"
        app:layout_collapseMode="pin">

        <include
               android:id="@+id/toolbar_open"
               ayout="@layout/include_toolbar_open"/>

        <include
               android:id="@+id/toolbar_close"
               layout="@layout/include_toolbar_close"/>

</androidx.appcompat.widget.Toolbar>

toolbar 里的两个布局,可以通过监听 AppBarLayout 的移动控制显示和隐藏。

4、滑动过程中,各控件的透明度会有渐变的效果,这里采用类似遮罩的效果,每个 include 布局里都有个遮罩的 view,在滑动过程中监听 appBarLayoutaddOnOffsetChangedListener,通过计算滑动的距离,逐渐改变透明度。

/**
     * 通过计算滑动的距离,逐渐改变透明度。
     */
    override fun onOffsetChanged(appBarLayout: AppBarLayout, verticalOffset: Int) {
        //垂直方向偏移量
        val offset = Math.abs(verticalOffset)
        //最大偏移距离
        val scrollRange = appBarLayout.totalScrollRange
        //当滑动没超过一半,展开状态下 toolbar 显示内容,更具收缩位置,改变透明值
        if (offset <= scrollRange / 2) {
            toolbar_open.visibility = View.VISIBLE
            toolbar_close.visibility = View.GONE
            //根据偏移百分比 计算透明值
            val scale: Float = offset.toFloat() / (scrollRange / 2)
            val alpha: Int = (255 * scale).toInt()
            bg_toolbar_open.setBackgroundColor(Color.argb(alpha, 25, 131, 209))
        }
        //当滑动超过一半,收缩状态下 toolbar 显示内容,根据收缩位置,改变透明值
        else {
            toolbar_open.visibility = View.GONE
            toolbar_close.visibility = View.VISIBLE
            val scale = (scrollRange - offset).toFloat() / (scrollRange / 2)
            val alpha = (255 * scale).toInt()
            bg_toolbar_close.setBackgroundColor(Color.argb(alpha, 25, 131, 209))
        }
        //根据百分比计算扫一扫布局透明值
        val scale = offset.toFloat() / scrollRange
        val alpha = (255 * scale).toInt()
        bg_content.setBackgroundColor(Color.argb(alpha, 25, 131, 209))
    }

详细代码见 :
github地址:https://github.com/wuchao226/AliHome

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342