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

标签 java android animation android-recyclerview android-animation

我正在为我的 RecyclerView 构建一个变化动画。我重写了 canReuseUpdatedViewHolder() 以返回 true 以保留之前的 viewholder。我在 animateChange() 中启动动画,并在它结束后立即调用 dispatchAnimationFinished()。参数 oldHoldernewHolderanimateChange() 中的同一个实例。

然后,一旦动画开始,就会为列表中的每个 child 调用 RecyclerView 的 onBindViewHolder()。令人惊讶的是,只有动画项目才会在 onCreateViewHolder() 中生成一个新的 ViewHolder,据我所知这不是正确的行为。对于所有其他子级,旧 ViewHolder 都绑定(bind)在 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;
    }
}

这是自定义 View 动画代码:

自定义 View .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 的状态已经改变。也许你可以这样做

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

关于java - 即使 ItemAnimator.canReuseUpdatedViewHolder() 返回 true,OnCreateViewHolder 仍然被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39223850/

相关文章:

android - 使用 3d 翻转动画开始 Activity

java - 我可以改进这个 Pig-Latin 转换器吗?

在 ICS 中使用 ViewPager 更改 Android 背景颜色

android - AsyncTask 没有取消 android 中长时间运行的操作

Android:抽屉导航 fragment 内的Viewpager

android - 单击按钮时动画不会第二次应用

html - svg 必须是内联的才能使用 javascript 查询其节点之一吗?

java - 我该如何修复此错误 : non supported SQL92?

java - 是否有 Hamcrest 匹配器来检查 Collection 既不为空也不为空?

java - 取消定义 packageName 并捕获图标