即使ItemAnimator.canReuseUpdatedViewHolder()返回true,仍会调用OnCreateViewHolder [英] OnCreateViewHolder is still called even if ItemAnimator.canReuseUpdatedViewHolder() returns true
问题描述
我正在为我的RecyclerView构建一个更改动画。我已经覆盖 canReuseUpdatedViewHolder()
以返回 true
,以便保留上一个视图。我在 animateChange()
中启动动画,并在结束时立即调用 dispatchAnimationFinished()
。参数 oldHolder
和 newHolder
是 animateChange()
。
I'm building a change animation for my RecyclerView. I've overriden canReuseUpdatedViewHolder()
to return true
in order to retain the previous viewholder. I start the animation in animateChange()
and call dispatchAnimationFinished()
as soon as it ends. Params oldHolder
and newHolder
are the same instance in animateChange()
.
然后,一旦动画开始,就会为列表中的每个孩子调用RecyclerView的 onBindViewHolder()
。令人惊讶的是,仅对于动画项目,在 onCreateViewHolder()
中生成了一个新的ViewHolder,正如我所理解的那样,这是不正确的行为。对于每个其他孩子,旧的ViewHolder绑定在 onBindViewHolder()
。
Then, as soon as the animation starts, RecyclerView's onBindViewHolder()
is called for every child in the list. Surprisingly, only for the animated item a new ViewHolder is spawned in onCreateViewHolder()
which as I've understood is not the correct behavior. For every other child the old ViewHolder is bound in onBindViewHolder()
.
作为附注,<$ c在动画结束之前,很快就会调用$ c> onBindViewHolder()。即使在动画结束后调用 dispatchAnimationFinished(holder)
。
As a side note, onBindViewHolder()
is called too soon, before the animation is finished. Even if dispatchAnimationFinished(holder)
is called after the animation is finished.
这是ItemAnimator子类。
Here's the ItemAnimator subclass.
public class CustomItemAnimator extends DefaultItemAnimator {
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
return true;
}
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull List<Object> payloads) {
return true;
}
@Override
public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
CustomHolder holder = (CustomHolder) newHolder;
CustomView customView = holder.customView;
Animator animator = customView.revealAnimation();
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
dispatchAnimationFinished(holder);
}
});
animator.start();
return false;
}
}
这里是自定义视图动画代码:
and here's the custom view animation code:
CustomView.java
public Animator revealAnimation() {
return circularRevealView(visibleView, hiddenView);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private Animator circularRevealView(View visibleView, View invisibleView) {
// get the center for the clipping circle
int cx = visibleView.getWidth() / 2;
int cy = visibleView.getHeight() / 2;
// get the final radius for the clipping circle
float finalRadius = (float) Math.hypot(cx, cy);
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(invisibleView, cx, cy, 0, finalRadius);
visibleView.setVisibility(INVISIBLE);
invisibleView.setVisibility(View.VISIBLE);
// return the animation for later use
return anim;
}
谢谢。
推荐答案
animateChange(...)在notifyDataSetChanged()之后调用,这意味着onBindViewHolder()在animateChange(...)之前。并且holder的状态已经改变。可能是你可以做到这一点
animateChange(...) is called after notifyDataSetChanged(),it means that onBindViewHolder() goes before animateChange(...).and the state of holder has already changed.maybe you can do it this
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
visibleView.setVisibility(INVISIBLE);
invisibleView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
dispatchAnimationFinished(holder);
}
});
这篇关于即使ItemAnimator.canReuseUpdatedViewHolder()返回true,仍会调用OnCreateViewHolder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!