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

自定义ItemAnimator中animateChange的oldHolder无动画问题求助

Troubleshooting Old Holder Not Redrawing in RecyclerView ItemAnimator's animateChange()

Hey there! Let's break down why your oldHolder isn't redrawing even after updating its layout params in the animateChange() method—this is a common gotcha with RecyclerView's item animations.

Possible Causes & Fixes

  1. Old Holder's View Might Be Detached or Marked for Recycling
    RecyclerView often marks the old holder as "pending removal" once the change animation starts. If oldHolder.itemView.getParent() returns null, that means it's already been detached from the RecyclerView, so updating its layout params won't trigger any redraw.

    • Fix: Ensure you're not prematurely calling recyclerView.recycleView(oldHolder) or letting RecyclerView auto-recycle it before the animation finishes. In your animateChange() implementation, hold onto the old holder until the animation completes, then call dispatchChangeFinished(oldHolder, false) to let RecyclerView know it can be recycled safely.
  2. Layout Params Updates Aren't Being Recognized
    Sometimes just modifying the existing LayoutParams object isn't enough—RecyclerView's LayoutManager might not detect the change. You need to explicitly reassign the params to trigger a layout pass.

    • Fix: In your ValueAnimator's update listener, after modifying the height, reassign the params to the view:
      val oldParams = oldHolder.itemView.layoutParams
      oldParams.height = currentHeight
      oldHolder.itemView.layoutParams = oldParams // Reassign to trigger detection
      oldHolder.itemView.requestLayout()
      
  3. Explicitly Trigger Layout & Redraw
    Even if isLayoutRequested() returns true, the system might not prioritize processing that request for a view that's being replaced. Force the issue by calling both requestLayout() (to update layout) and invalidate() (to trigger redraw) on the old holder's item view.

    • Add these lines after updating params:
      oldHolder.itemView.requestLayout()
      oldHolder.itemView.invalidate()
      
  4. Try Using View's Built-in Animation Instead
    If manual ValueAnimator handling is causing headaches, leverage the View.animate() API, which handles layout and redraw automatically:

    oldHolder.itemView.animate()
        .height(FINAL_HEIGHT)
        .setDuration(yourAnimationDuration)
        .setListener(object : Animator.AnimatorListener {
            override fun onAnimationEnd(animation: Animator?) {
                dispatchChangeFinished(oldHolder, false)
            }
            // Implement other listener methods as needed
        })
        .start()
    

Quick Check List

  • Verify oldHolder.itemView.isAttachedToWindow() returns true at the start of the animation.
  • Ensure the old holder's view isn't set to View.GONE or View.INVISIBLE.
  • Double-check that your LayoutManager isn't overriding the height params (e.g., LinearLayoutManager with match_parent might ignore explicit heights if not configured properly).

Hope these tips get your old holder animating correctly!

内容的提问来源于stack exchange,提问作者M. Palsich

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:41:40