You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决RecyclerView中MotionLayout实现的列表项动画滚动时混乱的问题

问题根源及修复方案

核心问题

滚动动画混乱是三个原因共同导致的:

  • 没有将MotionLayout的展开/收起状态绑定到数据源,仅存在View上,ViewHolder复用时会携带之前item的状态
  • 调用带动画的transitionToStart()重置状态时,滚动过程中动画未执行完成就被再次复用,出现视觉错乱
  • MotionScene中自带的<OnClick>触发器和数据源状态无关联,点击触发的状态不会同步到数据源

具体修复步骤

1. 给数据源加状态标记

在Story数据类中新增字段存储展开状态:

data class Story(
    // 原有字段保持不变
    var isExpanded: Boolean = false
)

2. 绑定数据时无动画重置状态

修改ViewHolder的set()方法,绑定数据时直接切到对应状态,不要走过渡动画:

fun set(story: Story) {
    this.story = story
    Glide
        .with(mainView.context)
        .load(story.image)
        .centerCrop()
        .into(storyImage)

    storyTitleTv.text = story.title
    storyAuthorTv.text = "" 
    addTags(story.tags)

    // 新增:无动画直接切到对应状态
    root.apply {
        if (story.isExpanded) {
            setProgress(1f)
        } else {
            setProgress(0f)
        }
    }
}

3. 移除MotionScene自带点击触发器,自行控制状态切换

首先删除MotionScene中<Transition>标签下的<OnClick motion:targetId="@+id/story_image" />代码。
然后修改ViewHolder中storyImage的点击逻辑,同步更新数据源状态:

init {
    // 原有其他点击逻辑保持不变
    storyImage.setOnClickListener {
        story.isExpanded = !story.isExpanded
        if (story.isExpanded) {
            root.transitionToEnd()
        } else {
            root.transitionToStart()
        }
    }
}

4. 可选优化:复用时立即停止动画

在ViewHolder中新增回收回调方法,复用时直接终止未完成的动画,避免状态错乱:

fun onRecycled() {
    // 立即结束当前所有过渡动画
    root.transitionToState(root.currentState, 0)
}

在Adapter的onViewRecycled()方法中调用该方法即可。

额外注意

你当前的start ConstraintSet是空的,建议把布局初始状态的约束明确写到start标签里,不要依赖MotionLayout自动解析布局默认约束,避免部分系统版本出现解析异常。


内容的提问来源于stack exchange,提问作者MoonX App

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 08:39:04