写点什么

Android:手把手教你实现在 XML 中配置网易云歌手详情滑动效果

用户头像
Android架构
关注
发布于: 刚刚

//新增属性


app:extend_height="30%">


<androidx.appcompat.widget.AppCompatImageView


android:layout_width="match_parent"


android:layout_height="300dp"


android:src="@drawable/singer"


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 滑动中的几种状态。



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<in V: View> {


/**


  • @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]

  • @par


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


am 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,

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android:手把手教你实现在XML中配置网易云歌手详情滑动效果