2

Ich erstelle eine Änderungsanimation für meine RecyclerView. Ich habe canReuseUpdatedViewHolder() überschrieben, um true zurückzugeben, um den vorherigen viewholder beizubehalten. Ich beginne die Animation in animateChange() und rufe dispatchAnimationFinished() an, sobald es endet. Params oldHolder und newHolder sind die gleiche Instanz in animateChange().OnCreateViewHolder wird auch dann aufgerufen, wenn ItemAnimator.canReuseUpdatedViewHolder() True zurückgibt

Sobald die Animation startet, wird RecyclerViews onBindViewHolder() für jedes Kind in der Liste aufgerufen. Überraschenderweise wird nur für das animierte Element ein neuer ViewHolder in onCreateViewHolder() erzeugt, der, wie ich verstanden habe, nicht das richtige Verhalten ist. Für jedes andere Kind wird der alte ViewHolder in onBindViewHolder() gebunden.

Als Randnotiz wird onBindViewHolder() zu früh aufgerufen, bevor die Animation beendet ist. Auch wenn dispatchAnimationFinished(holder) aufgerufen wird, nachdem die Animation beendet ist.

Hier ist die ItemAnimator-Unterklasse.

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

und hier ist die benutzerdefinierte Ansicht 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; 
} 

Dank.

Antwort

1

animateChange (...) nach notifyDataSetChanged() aufgerufen wird, bedeutet dies, dass onBindViewHolder() vor animateChange geht (...). Und der Zustand der Inhaber hat bereits changed.maybe Sie es dieses

tun können
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); 
      } 
     }); 
Verwandte Themen