即使 ItemAnimator.canReuseUpdatedViewHolder() 返回 true,OnCreateViewHolder 仍会被调用

2024-03-03

我正在为我的 RecyclerView 构建更改动画。我已经覆盖了canReuseUpdatedViewHolder()回来true以保留先前的观看者。我开始动画animateChange()并打电话dispatchAnimationFinished()一旦结束。参数oldHolder and newHolder是同一个实例animateChange().

然后,一旦动画开始,RecyclerView 的onBindViewHolder()为列表中的每个孩子调用。令人惊讶的是,只有动画项目才会生成新的 ViewHolderonCreateViewHolder()据我了解,这不是正确的行为。对于每个其他孩子,旧的 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;
}

Thanks.


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);
            }
        });
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

即使 ItemAnimator.canReuseUpdatedViewHolder() 返回 true,OnCreateViewHolder 仍会被调用 的相关文章

随机推荐