XML中配置网易云歌手详情滑动效果

android:scaleType=“centerCrop”

//新增属性

app:transformation=“scroll|extend_scale”

/>

</com.zzx.headerlayout_kotlin.HeaderLayout>

<androidx.viewpager.widget.ViewPager

android:id=“@+id/viewPager”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

//配置依赖布局的layout_behavior

app:layout_behavior=“@string/header_layout_scrolling_view_behavior”/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

如上所示,HeaderLayout工作在CoordinatorLayout中并且是其直接子View。ViewPager由于需要根据HeaderLayout的滑动做出界面的调整,所以需要配置layout_behavior,并且其值为@string/header_layout_scrolling_view_behavior,这里和AppBarLayout的使用方式一致。我们的工作重点是头部控件的联动效果,因此咱们聚焦于HeaderLayout和其子View。我们看AppCompatImageView,它用来展示效果图中的歌手。仔细分析效果图中AppCompatImageView的变换方式,可以发现它是根据父控件HeaderLayout的滑动而做出的相应的变化效果,HeaderLayout向上滑动,其跟随向上,HeaderLayout向下滑动,则跟着向下。并且,在HeaderLayout滑动到底部继续向下拓展时,AppCompatImageView做了一个收缩的变换。这一切的一切都需要归功于app:transformation属性,可以在代码中看见其值为"scroll|extend_scale",那么其含义是什么呢?对此,我们引出了一个概念----Transformation,它是一个接口,其意在为根据HeaderLayout的滑动及状态而做出相应的变化行为。在介绍Transformation之前,有必要介绍一下HeaderLayout滑动中的几种状态。

HeadeerLayout状态图

HeaderLayout的滑动实际上是HeaderLayout高度的动态变化,所以需要了解图中三种高度的含义。maxHeight是HeaderLayout第一次加载测量后的高度,minHeight是设置了app:sticky_until_exit="true"属性的子View的高度之和,此属性表示子View不随着HeaderLayout而滑出屏幕,形成一种粘连在屏幕顶部的效果,且子View是按照顺序排列的。extendHeight则是拓展的高度,展示在效果图中就是图片收缩scale时下滑的高度,extendHeight可以在xml中为HeaderLayout设置,其值可以为dimension,百分数,或者float比例,百分数和float比例是按照maxHeight而计算的。

而图中五种状态用来表示HeaderLayout高度变化过程中用来表示滑动状态的,Transformation就是根据应这五种状态而生,Transformation作用于HeaderLayout的直接子View或者间接子View(间接子View需要自己进行处理,可以参考CommonToolbarTransformation),一个子View可以同时拥有多个Transformation,HeaderLayout在其状态变化时,则会遍历子View的所有Transformation,通知其做出改变。

XML中作用于AppCompatImageView的app:transformation="scroll|extend_scale"属性,scroll 和 extend_scale则是内置的两种Transformation,如下表所示。

transformation表示内置的几中Transformation,但是想要自定义Transformation应该如何做呢?

自定义Transformation


custom_transformation属性则是专为自定义Transformation而服务,其值为自己实现的Transformation类的全路径。自定义Transformation有两种方式,其一是实现Transformation接口,另一种方式是继承TransformationAdapter类,TransformationAdapter是Transformation是Transformation接口的空实现,继承于此则不需要实现所有的方法。

interface Transformation {

/**

  • @see [HeaderLayout.scrollState]为STATE_MIN_HEIGHT, 这个方法回调表示[HeaderLayout]的Bottom已经收缩到了最小高度

  • @param child 当前需要做变换的view

  • @param parent [HeaderLayout]

  • @param unConsumedDy 由其他状态到此状态未消耗完的dy

*/

fun onStateMinHeight(child: V, parent: HeaderLayout, unConsumedDy: Int)

/**

  • @see [HeaderLayout.scrollState]为STATE_NORMAL_PROCESS, 在STATE_MIN_HEIGHT和STATE_MAX_HEIGHT之间

  • 这个方法回调表示[HeaderLayout]的Bottom正在最小高度与最大高度之间

  • @param child 当前需要做变换的view

  • @param parent [HeaderLayout]

  • @param percent 0<percent<1, 值为([HeaderLayout.getBottom] - [HeaderLayout.minHeight]) / ([HeaderLayout.maxHeight] - [HeaderLayout.minHeight]])

  • 且值不会为0或者1, 为0相当于是回调了[onStateMinHeight], 为1相当于回调了[onStateMaxHeight], 由于值不会为0或1,

  • 所以在回调[onStateMinHeight]和[onStateMaxHeight]时会有一个未消耗的dy

  • @param dy 滑动的距离

*/

fun onStateNormalProcess(child: V, parent: HeaderLayout, percent: Float, dy: Int)

/**

  • @see [HeaderLayout.scrollState]为STATE_MAX_HEIGHT

  • 这个方法回调表示[HeaderLayout]的Bottom正处于[HeaderLayout.maxHeight]

  • @param child 当前需要做变换的view

  • @param parent [HeaderLayout]

  • @param unConsumedDy 由其他状态到此状态未消耗完的dy

*/

fun onStateMaxHeight(child: V, parent: HeaderLayout, unConsumedDy: Int)

/**

  • @see [HeaderLayout.scrollState]为STATE_EXTEND_PROCESS, 在STATE_MAX_HEIGHT和STATE_EXTEND_MAX_END之间

  • 这个方法回调表示[HeaderLayout]的Bottom正处于[HeaderLayout.maxHeight] 和 [HeaderLayout.maxHeight] + [HeaderLayout.extendHeight]之间

  • @param child 当前需要做变换的view

  • @param parent [HeaderLayout]

  • @param percent 0<percent<1, 值为([HeaderLayout.getBottom] - [HeaderLayout.maxHeight]) / [HeaderLayout.extendHeight]

  • 且值不会为0或者1, 为0相当于是回调了[onStateMaxHeight], 为1相当于回调了[onStateExtendMaxEnd], 由于值不会为0或1,

  • 所以在回调[onStateMaxHeight]和[onStateExtendMaxEnd]时会有一个未消耗的dy

*/

fun onStateExtendProcess(child: V, parent: HeaderLayout, percent: Float, dy: Int)

/**

  • @see [HeaderLayout.scrollState]为STATE_EXTEND_MAX_END,

  • 这个方法回调表示[HeaderLayout]的Bottom正处于[HeaderLayout.maxHeight] + [HeaderLayout.extendHeight]

  • @param child 当前需要做变换的view

  • @param parent [HeaderLayout]

  • @param unConsumedDy 由其他状态到此状态未消耗完的dy

*/

fun onStateExtendMaxEnd(child: V, parent: HeaderLayout, unConsumedDy: Int)

}

HeaderLayout在状态变化的时候会遍历子View的所有Transformation,也即是会回调Transformation接口中的这几个方法,使用者可以根据这几个方法的含义来变换子View。

Tips


开发者在使用app:transformation和app:sticky_untila_exit等属性时,最好用AppCompatImageView代替ImageView,AppCompatTextView代替TextView,这样在XML文件中则不会因为系统控件无法使用自定义属性而报红线,即使报红线也不会影响程序正常的执行,只是看着别扭。

最后:学习总结——Android框架体系架构知识脑图(纯手绘xmind文档)

学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。

下方即为我手绘的Android框架体系架构知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的Android框架体系架构知识脑图原件(包括上方的面试解析xmind文档)

除此之外,前文所提及的Alibaba珍藏版 Android框架体系架构 手写文档以及一本 《大话数据结构》 书籍等等相关的学习笔记文档,也皆可分享给认可的朋友!

——感谢大家伙的认可支持,请注意:点赞+点赞+点赞!!!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
]

除此之外,前文所提及的Alibaba珍藏版 Android框架体系架构 手写文档以及一本 《大话数据结构》 书籍等等相关的学习笔记文档,也皆可分享给认可的朋友!

——感谢大家伙的认可支持,请注意:点赞+点赞+点赞!!!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值