web-dev-qa-db-fra.com

Comment implémenter ItemAnimator of RecyclerView pour désactiver l'animation de notifyItemChanged

Dans mon projet, il faut désactiver l'animation "change" de RecyclerView tandis que notifyItemChanged.

J'ai enquêté dans la source de RecyclerView et j'avais écrasé Android.support.v7.widget.DefaultItemAnimator comme ci-dessous:

private static  class ItemAnimator extends DefaultItemAnimator
{
    @Override
    public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromX, int fromY, int toX, int toY) {
        if(oldHolder != null)
        {
            oldHolder.itemView.setVisibility(View.INVISIBLE);
            dispatchChangeFinished(oldHolder, true);
        }

        if(newHolder != null)
        {
            dispatchChangeFinished(newHolder, false);
        }

        return false;
    }
}

Mais je ne suis pas sûr de correspondre aux spécifications du document Google: RecyclerView.ItemAnimator.animateChange

D'après ce que je comprends du code source, si je ne substitue pas la méthode correctement, oldHolder ne sera pas être recyclé.

S'il vous plaît, aidez-moi à comprendre comment remplacer animateChange de manière correcte.

57
Kenny

J'ai trouvé la bonne solution pour supprimer simplement animateChange.

C'est très simple. Google a implémenté la fonctionnalité.

((SimpleItemAnimator) RecyclerView.getItemAnimator()).setSupportsChangeAnimations(false);

Documentation: setSupportsChangeAnimations

109
Kenny

J'ai eu le même problème. Lors de l'appel de notifyItemChanged, un calque rouge clignotait. Après avoir expérimenté votre code, j'ai finalement supprimé l'animateur par défaut en appelant simplement

recyclerView.setItemAnimator(null);

sur le RecyclerView.

49
Saenic

La réponse de @Kenny n'a plus fonctionné parce que la méthode de suppression de Google setSupportsChangeAnimations() (mais pourquoi?) Dans la bibliothèque de support 23.1.0.

Dans certains cas, setChangeDuration(0) peut fonctionner comme solution de contournement.

@edit je suggère d'utiliser quelque chose comme ça:

  RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
        if (animator instanceof SimpleItemAnimator) {
            ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
        }
8
Shu

Juste si quelqu'un trébuche comme moi:
D'une manière ou d'une autre setSupportsChangeAnimations(false) n'a pas fonctionné pour moi, mais recyclerView.getItemAnimator().setChangeDuration(0) vient de supprimer correctement l'animation.

4
Touhid

Si trouvé une solution, pour tout le monde qui veut garder toutes les animations données par le DefaultItemAnimator, mais se débarrasser de l'animation "clignotant" qui se produit chaque fois que la vue est mise à jour.

Commencez par obtenir le code source de DefaultItemAnimator. Créez une classe avec le même nom dans votre projet.

Deuxièmement, définissez ItemAnimator sur une nouvelle instance de votre DefaultItemAnimator modifié, comme suit:

recyclerView.setItemAnimator(new MyItemAnimator());

Ensuite, allez dans le code source des nouvelles classes et localisez la méthode

animateChangeImpl(final ChangeInfo changeInfo) { ... }

Maintenant, nous devons simplement localiser les appels de méthodes qui changent les valeurs alpha. Recherchez les deux lignes suivantes et supprimez les fichiers .alpha (0) et .alpha (1)

oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() { ... }
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).alpha(1).setListener(new VpaListenerAdapter() { ... }

ainsi

oldViewAnim.setListener(new VpaListenerAdapter() { ... }
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).setListener(new VpaListenerAdapter() { ... }
4
Alex

La solution la plus simple consiste à étendre DefaultItemAnimator et à définir setSupportsChangeAnimations à false directement dans le constructeur:

public class DefaultItemAnimatorNoChange extends DefaultItemAnimator {
    public DefaultItemAnimatorNoChange() {
        setSupportsChangeAnimations(false);
    }
}
2
rafakob