自定义ItemAnimator中animateChange的oldHolder无动画问题求助
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
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. IfoldHolder.itemView.getParent()returnsnull, 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 youranimateChange()implementation, hold onto the old holder until the animation completes, then calldispatchChangeFinished(oldHolder, false)to let RecyclerView know it can be recycled safely.
- Fix: Ensure you're not prematurely calling
Layout Params Updates Aren't Being Recognized
Sometimes just modifying the existingLayoutParamsobject 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()
- Fix: In your ValueAnimator's update listener, after modifying the height, reassign the params to the view:
Explicitly Trigger Layout & Redraw
Even ifisLayoutRequested()returnstrue, the system might not prioritize processing that request for a view that's being replaced. Force the issue by calling bothrequestLayout()(to update layout) andinvalidate()(to trigger redraw) on the old holder's item view.- Add these lines after updating params:
oldHolder.itemView.requestLayout() oldHolder.itemView.invalidate()
- Add these lines after updating params:
Try Using View's Built-in Animation Instead
If manual ValueAnimator handling is causing headaches, leverage theView.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()returnstrueat the start of the animation. - Ensure the old holder's view isn't set to
View.GONEorView.INVISIBLE. - Double-check that your LayoutManager isn't overriding the height params (e.g.,
LinearLayoutManagerwithmatch_parentmight ignore explicit heights if not configured properly).
Hope these tips get your old holder animating correctly!
内容的提问来源于stack exchange,提问作者M. Palsich

