【问题标题】:OnCreateViewHolder is still called even if ItemAnimator.canReuseUpdatedViewHolder() returns true即使 ItemAnimator.canReuseUpdatedViewHolder() 返回 true,仍会调用 OnCreateViewHolder
【发布时间】:2016-08-30 09:34:32
【问题描述】:

我正在为我的 RecyclerView 构建一个更改动画。我已经覆盖 canReuseUpdatedViewHolder() 以返回 true 以保留以前的视图。我在animateChange() 中开始动画,并在结束后立即调用dispatchAnimationFinished()。参数oldHoldernewHolderanimateChange() 中的同一个实例。

然后,只要动画开始,就会为列表中的每个孩子调用 RecyclerView 的 onBindViewHolder()。令人惊讶的是,仅对于动画项目,onCreateViewHolder() 中才会生成一个新的 ViewHolder,据我所知,这不是正确的行为。对于每个其他孩子,旧的 ViewHolder 都绑定在 onBindViewHolder() 中。

作为旁注,onBindViewHolder() 在动画完成之前被调用得太早。即使动画结束后调用dispatchAnimationFinished(holder)

这是 ItemAnimator 子类。

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;
    }
}

这是自定义视图动画代码:

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;
}

谢谢。

【问题讨论】:

    标签: java android animation android-recyclerview android-animation


    【解决方案1】:

    animateChange(...)是在notifyDataSetChanged()之后调用的,表示onBindViewHolder()在animateChange(...)之前,并且holder的状态已经改变了。也许你可以这样做

    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);
                }
            });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-14
      • 2019-12-15
      • 1970-01-01
      • 1970-01-01
      • 2010-11-02
      相关资源
      最近更新 更多