Ich arbeite an einer App, die Bilder von einer Website anzeigt. Die Bilder haben alle unterschiedliche Höhen. Dies gilt auch für die Ansichten (Viewholders), in denen sie angezeigt werden.Probleme beim Ersetzen des Datensatzes von RecyclerView
Beim Anwenden eines Filters wird der vorherige Datensatz (also der derzeit sichtbare) entfernt, indem er direkt aus dem Datensatz gelöscht wird Adapter. Der Adapter wird benachrichtigt, dass dies passierte mit
final int removedSize = items.size();
items.clear();
notifyItemRangeRemoved(0, removedSize);
Dies macht die alten Elemente animiert vom Bildschirm. Wenn diese Animation beendet ist, füge ich den neuen Datensatz mit
hinzu. Dies animiert die hinzugefügten Objekte. Das Seltsame ist, dass ich manchmal Lücken im RecyclerView bekomme, als ob der RecyclerView die neuen Dimensionen des ViewHolders beim Zeichnen aller Objekte nicht berücksichtigt. Dazu kommt, dass einige der Gegenstände buchstäblich übereinander liegen und wann immer sie wollen, in den Vordergrund treten. Die Gegenstände, die sich oben auf den Gegenständen befinden, die sich an der richtigen Position befinden, sind Gegenstände, die innerhalb der Lücken platziert werden sollten. Sie werden nicht in die Lücke zurückkehren, aber als ich den Gegenstandssatz manuell untersuchte, bemerkte ich, dass sie dort sein sollten.
Der RecyclerView ist das Kind einer SwipeRefreshLayout Ansicht, aber ich denke nicht, dass das ein Problem sein sollte.
Einige der Parameter I des RecyclerView festgelegt haben:
recents.setLayoutManager(layoutManager);
recents.setHasFixedSize(false);
recents.setItemViewCacheSize(100);
Innerhalb der Layout-Datei
android:animationCache="false"
android:scrollingCache="false"
Was mache ich falsch?
Ich habe bereits eine kleine Verzögerung von 0,7 Sekunden hinzugefügt, um sicherzustellen, dass alle Animationen beendet sind, aber das scheint nicht viel zu helfen.
ItemAnimator:
@Override
public boolean animateAdd(RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() != -8) { // ImageAdapter.ViewType.EMPTY = -8;
if (viewHolder.getLayoutPosition() > lastAddAnimatedItem) {
lastAddAnimatedItem++;
runEnterAnimation((ImageListView) viewHolder, viewHolder.getLayoutPosition());
return false;
}
}
lastAddAnimatedItem = -6;
dispatchAddFinished(viewHolder);
return false;
}
@Override
public boolean animateRemove(RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() != -8) { // ImageAdapter.ViewType.EMPTY = -8;
if (viewHolder.getLayoutPosition() > lastRemoveAnimatedItem) {
lastRemoveAnimatedItem++;
runExitAnimation((ImageListView) viewHolder, viewHolder.getLayoutPosition());
return false;
}
}
lastRemoveAnimatedItem = -6;
dispatchRemoveFinished(viewHolder);
return false;
}
private void runEnterAnimation(final ImageListView holder, int position) {
final int screenHeight = Utils.getScreenHeight(holder.itemView.getContext());
holder.itemView.setTranslationY(screenHeight + holder.itemView.getHeight());
holder.itemView.animate()
.translationY(0)
.setStartDelay(150 + (20 * (position)))
.setInterpolator(new DecelerateInterpolator(3.f))
.setDuration(700)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
dispatchAddFinished(holder);
}
})
.start();
}
private void runExitAnimation(final ImageListView holder, int position) {
final int screenHeight = Utils.getScreenHeight(holder.itemView.getContext());
holder.itemView.setTranslationY(0);
holder.itemView.animate()
.translationY(-screenHeight - holder.itemView.getHeight())
.setStartDelay(Math.abs(20 * (position)))
.setInterpolator(new DecelerateInterpolator(3.f))
.setDuration(700)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
dispatchRemoveFinished(holder);
}
})
.start();
}
EDIT:
Es scheint, dass das erste Element nach dem letzten sichtbaren Elemente, das auf dem Bildschirm an der falschen Stelle platziert.