RecyclerView使用LayoutTransition实现布局过渡动画

一、目标

在这里插入图片描述
上图为普通状态和编辑状态的界面图。

普通状态切换到编辑状态,需要切换删除按钮和拖拽按钮的可见性,并实现切换过程的动画效果。

二、体验地址

神马笔记最新版本:【神马笔记 版本1.3.0.apk

三、功能设计

如果不设置动画效果,整个界面的切换过程将会非常生硬。

因此,我们添加如下的过渡动画。

  • 切换到编辑状态
    • 删除按钮——从左侧淡入(translationX + alpha)
    • 拖拽按钮——从右侧进入(translationX)
  • 切换到普通状态
    • 删除按钮——从左侧淡出(translationX + alpha)
    • 拖拽按钮——从右侧退出(translationX)

四、准备工作

1. LayoutTransition

ViewGroup使用LayoutTransition即可为布局变化应用动画效果。

  • ViewGroup#setLayoutTransition(LayoutTransition)
  • android:animateLayoutChanges="true"

通过代码或者资源文件方式,都可以启用ViewGroup的布局过渡动画效果。

  • LayoutTransition支持5中情景的动画,但经常使用的只有4种。
常量定义 动画效果
CHANGE_APPEARING 其他控件出现时,自身的变化动画
CHANGE_DISAPPEARING 其他控件消失时,自身的变化动画
APPEARING 自身出现时的动画
DISAPPEARING 自身消失时的动画
CHANGING ViewGroup自身布局发生变化时,而不是子控件发生变化。默认关闭。
private int mTransitionTypes = FLAG_CHANGE_APPEARING | FLAG_CHANGE_DISAPPEARING |
    FLAG_APPEARING | FLAG_DISAPPEARING;
  • LayoutTransition动画的默认值。
动画常量 Delay Interpolator Animator
CHANGE_APPEARING 0 DECEL CHANGE动画
CHANGE_DISAPPEARING 300 DECEL CHANGE动画
APPEARING 300 ACCEL_DECEL ObjectAnimator.ofFloat(null, “alpha”, 0f, 1f)
DISAPPEARING 0 ACCEL_DECEL ObjectAnimator.ofFloat(null, “alpha”, 1f, 0f)
CHANGING 0 DECEL CHANGE动画

CHANGE动画

PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);
PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1);
PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1);
PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1);
PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1);

ObjectAnimator.ofPropertyValuesHolder
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Kotlin实现RecyclerView的多种item布局,需要创建多个ViewHolder来适配不同的布局类型。具体步骤如下: ```kotlin // 创建一个通用的ViewHolder类 class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { // 绑定数据的方法 fun bindData(data: Any) { // 根据不同的数据类型,绑定不同的布局 when (data) { is TypeA -> { // 绑定TypeA布局 } is TypeB -> { // 绑定TypeB布局 } // ... } } } // 创建一个通用的Adapter类 class BaseAdapter(private val dataList: List<Any>) : RecyclerView.Adapter<BaseViewHolder>() { // 根据不同的布局类型,创建不同的ViewHolder override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder { return when (viewType) { TYPE_A -> { // 创建TypeA布局ViewHolder } TYPE_B -> { // 创建TypeB布局ViewHolder } // ... else -> { // 创建默认布局ViewHolder } } } // 根据不同的数据类型,返回不同的布局类型 override fun getItemViewType(position: Int): Int { return when (dataList[position]) { is TypeA -> TYPE_A is TypeB -> TYPE_B // ... else -> DEFAULT_TYPE } } // 绑定数据到ViewHolder override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { holder.bindData(dataList[position]) } // 返回数据列表的大小 override fun getItemCount(): Int { return dataList.size } companion object { // 定义不同的布局类型 private const val TYPE_A = 0 private const val TYPE_B = 1 // ... private const val DEFAULT_TYPE = -1 } } ``` 在上述代码中,我们创建了一个通用的ViewHolder类和一个通用的Adapter类。ViewHolder类中的bindData方法根据不同的数据类型,绑定不同的布局。Adapter类中的getItemViewType方法根据不同的数据类型,返回不同的布局类型。在onCreateViewHolder方法中,根据不同的布局类型,创建不同的ViewHolder。在onBindViewHolder方法中,将数据绑定到ViewHolder上。最后,在RecyclerView中设置Adapter即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值