可折叠标题栏在很多的App上面现已频频运用了,而且原生的XML方式供给了现成的CollapsingToolbarLayout控件来帮助开发者完成可折叠标题栏,然而在Compose中,现在还没有现成的组件能够拿来即用,本文就经过MotionLayout+swipe来完成一个带吸顶功用的折叠标题栏。

在Compose运用MotionLayout,需求提前增加一下依靠:

implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha11")

现在最新版别为:1.1.0-alpha11,安稳版别还停留在:1.0.1

笔者在前面文章中现已介绍过如安在Compose中运用束缚布局:Jetpack Compose – 束缚布局ConstrainLayout

界说折叠状况

首先经过枚举类界说好折叠的状况,这儿界说两种状况:折叠COLLAPSED和打开EXPANDED

【Jetpack Compose】使用MotionLayout实现折叠标题栏

界说标题栏方位

咱们先看下标题栏折叠前和折叠后的两种作用图,折叠前左上角显现回来键,左下角是标题,整个标题栏布景是一张图片,折叠后布景图隐藏,回来键方位不变,标题则处于布局正中间。

【Jetpack Compose】使用MotionLayout实现折叠标题栏
【Jetpack Compose】使用MotionLayout实现折叠标题栏

依据上面两张作用图,咱们就能够把MotionLayout的开端和结束束缚集先界说完成,运用ConstrainSet界说布局的方位。

先界说起始束缚集

【Jetpack Compose】使用MotionLayout实现折叠标题栏

ConstrainSet中先界说好布景图、回来按钮、标题文本和下方的内容组件的引证,然后依据方位界说好四个引证的束缚条件

  • 布景图束缚条件:宽度全屏,顶部和父局对齐
  • 回来按钮束缚条件:左面和顶部都是和父布局对齐
  • 标题文本束缚条件:底部和布景图底部对齐,左面和父布局对齐,别离设置16dp的边距
  • 内容组件束缚条件:宽度全屏,顶部和标题底部对齐,设置顶部边距16dp

这样咱们就把标题栏的起始方位束缚集界说完了,下面咱们接着界说结束方位的束缚集

【Jetpack Compose】使用MotionLayout实现折叠标题栏

和起始方位的束缚集相同,还是先界说好布景图、回来按钮、标题文本和下方的内容组件的引证,然后依据方位界说好四个引证的束缚条件

  • 布景图束缚条件:宽度全屏,高度终究定格56dp,顶部、左右和父布局对齐
  • 回来按钮束缚条件:左面和顶部都是和父布局对齐,方位不变,束缚条件也不变
  • 标题文本束缚条件:左右和父布局对齐,这样能够完成水平居中的作用,然后顶部、底部和回来按钮对齐,这样标题文本和回来按钮就在同一水平线上
  • 内容组件束缚条件:宽度全屏,顶部和布景图底部对齐

到这停止咱们就把标题栏折叠前后的束缚集都界说完成了,下面咱们就能够直接把界说好的束缚集传给MotionLayout对应的参数即可。

【Jetpack Compose】使用MotionLayout实现折叠标题栏

MotionLayout有四个必传的参数:

  • start为起始方位的束缚集
  • end为结束方位的束缚集
  • progress整个动画进程的进度,在这能够看作折叠进程的进度
  • content内容组件

startend便是咱们上面界说好的束缚集,progress从外层传入,这儿暂时先不着急管,在内容组件中咱们把标题文本、回来按键、标题布景和标题下方组件界说好。

这儿需求留意的两点便是,每个组件的layoutId有必要和束缚集中的引证id保持一致;还有一点便是布景图片的透明度随着progress逐渐变得不可变,在折叠状况下布景图片是不显现的,只显现它的布景颜色。

手势处理

界说好折叠标题栏方位和组件之后,接下来就需求处理上滑和下滑的手势事情了。在开端编码之前,先理一下处理的思路。

  • 滑动手势能够经过swipeable修饰符来处理,它记载折叠的状况,也便是文章最开端的CollapsingState,默以为打开状况,而且它还能够处理吸顶的作用,吸顶的阈值界说为0.4
  • 嵌套滑动能够经过NestedScrollConnection来处理,上滑的进程中,先将滑动事情交给swipeable,让它先处理状况栏的折叠事情,等到状况栏彻底折叠之后,再将滑动事情交给父布局处理底部内容组件的滑动。

下面咱们来看详细代码完成

【Jetpack Compose】使用MotionLayout实现折叠标题栏

这一部分的代码可能有点长,但是在重点的地方都增加了注释方便咱们了解。

先看下嵌套滑动的部分NestedScrollConnection,这儿咱们复写了三个办法:

  • onPreScroll用来绑架预滑动事情,在手指上下滑动的开端咱们先处理下向上滑动事情,处理的逻辑便是上面介绍的,先将滑动事情交给swipeable,让它先处理状况栏的折叠事情,等到状况栏彻底折叠之后,再将滑动事情交给父布局处理底部内容组件的滑动,向下滑动的事情则不绑架,直接交给父布局处理。
  • onPostScroll获取子布局的滑动事情,这儿只需求处理笔直方向的滑动,交给swipeable即可。
  • onPostFling这个事情是处理手指松开的逻辑,因为想完成在上下滑进程中到达某一个阈值的时候标题栏是否主动折叠或许打开,就需求交给swipeable来判断,阈值会在下面swipeable修饰符中界说。

接下来再看下整个布局,全体布局外部选用Box组件,然后给它增加swipeable修饰符,界说好它的statethresholds,滑动的方向为Vertical笔直方向,这儿的anchors需求留意下,当锚点在0方位是它是折叠状况,当它的锚点为最大高度时它是打开状况,这也很容易了解。而且还需求给Box增加nestedScroll修饰符让它处理嵌套滑动的事情。

最后还记得上面提到的progress进度值么?CollapsingHeader的进度值经过滑动的进度来判断,

当它进度朝着折叠状况移动的时候,progress便是swipingState.progress.fraction;反之便是1 - swipingState.progress.fractionfraction是一个[0 – 1]的区间规模,它代表着滑动事情fromto的一个份额,也便是整个滑动事情进度的份额。

到这停止咱们就将一个折叠标题栏的脚手架给搭起来了,最后咱们只需求调用它并传递对应的参数即可,咱们来看下调用处的代码

【Jetpack Compose】使用MotionLayout实现折叠标题栏

这儿标题栏的下方内容咱们传入一个列表,列表的item传入最简单的文本组件,运转一下看看折叠标题栏的作用

GIF因为过大这儿压缩了一下,稍微影响了一点清晰度,咱们见谅,想要体验下作用的能够自己运转下代码实际感受下~

关于我

我是Taonce,如果觉得本文对你有所帮助,帮助重视、赞或许保藏三连一下,谢谢~