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.