2

Я создаю анимацию изменений для своего RecyclerView. Я заработал canReuseUpdatedViewHolder(), чтобы вернуть true, чтобы сохранить предыдущий зритель. Я начинаю анимацию в animateChange() и звоню dispatchAnimationFinished(), как только она заканчивается. Парамеры oldHolder и newHolder - это тот же экземпляр в animateChange().OnCreateViewHolder по-прежнему вызывается, даже если ItemAnimator.canReuseUpdatedViewHolder() возвращает true

Затем, как только начинается анимация, RecyclerView's onBindViewHolder() вызывается для каждого дочернего элемента в списке. Удивительно, но только для анимированного предмета новый ViewHolder создается в onCreateViewHolder(), который, как я понял, не соответствует правильному поведению. Для каждого другого ребенка старый 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; 
} 

Спасибо.

ответ

1

animateChange (...) вызывается после notifyDataSetChanged(), это означает, что onBindViewHolder() идет перед animateChange (...). И состояние держателя уже changed.maybe вы можете сделать это таким

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); 
      } 
     }); 
Смежные вопросы