RecyclerView StaggeredGridLayoutManager réorganisation de problème
J'essaie d'afficher trois (au moins c'est le cas, j'ai un problème avec) des éléments dans un RecyclerView
avec un StaggeredGridLayoutManager
avec deux colonnes. Le premier élément est fractionné sur les deux lignes. Voici à quoi ça ressemble:
Maintenant, je suis en déplaçant l'élément "Item 2" de haut. Voici le code que j'appelle, dans la carte (c'est un exemple que j'ai écrit pour démontrer le problème que j'ai plus de complexité du projet):
private int findById(int id) {
for (int i = 0; i < items.size(); ++i) {
if (items.get(i).title.equals("Item " + id)) {
return i;
}
}
return -1;
}
//Moving the item "Item 2" with id = 2 and position = 0
public void moveItem(int id, int position) {
final int idx = findById(id);
final Item item = items.get(idx);
if (position != idx) {
items.remove(idx);
items.add(position, item);
notifyItemMoved(idx, position);
//notifyDataSetChanged();
}
}
Après, le tableau est très bien: [Item 2, Item 1, Item 3]
. Cependant, le point de vue est loin d'amende:
Si je touche le RecyclerView
(assez pour déclencher la overscroll effet si il n'y a pas assez d'éléments pour faire défiler), Point 2 se déplacer vers la gauche, là où je m'attendais à le voir en premier lieu (avec une belle animation):
Comme vous l'avez peut-être vu dans le code, j'ai essayé de remplacer notifyItemMoved(idx, position)
par un appel à notifyDataSetChanged()
. Il fonctionne, mais le changement n'est pas animé.
J'ai écrit un échantillon complet pour le démontrer et de le mettre sur GitHub. Il est presque minime (il y a des options pour déplacer l'élément à bascule et leur répartition).
Je ne vois pas ce que je peux faire de mal. Est-ce un bug avec StaggeredGridLayoutManager
? Je voudrais éviter notifyDataSetChanged()
que je tiens à garder une cohérence concernant les animations.
Edit: après quelques recherches, il n'est pas nécessaire pour un fractionné élément pour montrer le problème. J'ai enlevé la pleine échelle. Lorsque j'essaie de déplacer l'Élément 2 à la position 0, il ne bouge pas: Article 1 va après elle, et le Point 3 est déplacé sur la droite, j'ai donc: cellule vide, Point 2, de la nouvelle ligne, l'Article 1, Point 3. J'ai toujours la correcte mise en page après un parchemin.
Ce qui est plus intéressant, c'est que je n'ai pas de problème avec un GridLayoutManager
. J'ai besoin d'une pleine échelle de l'élément de sorte qu'il n'est pas une solution, mais je suppose que c'est effectivement un bug dans le StaggeredGridLayoutManager
...
gap strategy
est cochéeGAP_HANDLING_NONE
évite le déplacement d'éléments, mais j'ai toujours une mauvaise disposition. GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
est probablement le défaut, de toute façon, j'ai le même comportement avec lui que sans préciser quoi que ce soit.Oui je sais je dis juste que, après vous faites défiler la carte vérifie les lacunes et puis déplace les choses à la bonne place
OriginalL'auteur Marc Plano-Lesay | 2015-01-06
Vous devez vous connecter pour publier un commentaire.
Je n'ai pas de réponse complète, mais je peux vous diriger à la fois une solution de contournement et le rapport de bug (qui je crois est lié).
L'astuce pour la mise à jour de la mise en page de sorte qu'il ressemble à la seconde capture d'écran, c'est d'appeler
invalidateSpanAssignments()
sur leStaggeredGridLayoutManger
(sglm) après que vous avez appelénotifyItemMoved()
. Le "défi", c'est que si vous l'appelez immédiatement aprèsnIM()
, il ne s'exécute pas. Si vous avez du retard à l'appel de quelques ms, il le sera. Donc, dans votre référencé code pour MainActivity, j'ai fait votresglm
un champ privé:Et en bas dans le bloc de commutateurs, de référence dans un gestionnaire d':
Le résultat est que l'animation fonctionne toujours, la mise en page se termine de la façon dont vous le souhaitez. C'est un vrai quelque chose, mais il fonctionne. Je crois que c'est le même bug que j'ai trouvé et signalé sur le lien suivant:
https://code.google.com/p/android/issues/detail?id=93156
Pendant que mon "symptôme" et l'appel est différent, la question sous-jacente semble être identique.
Bonne chance!
EDIT: Pas besoin de postDelayed, il suffit de poster fera l'affaire:
Ma théorie originale est que l'appel a été bloqué jusqu'à la passe de mise en page est sur, mais je crois que ce n'est pas le cas. Au lieu de cela, maintenant je pense que si vous appelez
invalidateSpanAssignments()
immédiatement, il s'exécute en fait trop tôt (avant les modifications de mise en page ont complété). Donc, le post ci-dessus (sans retard) ajoute simplement l'appel à la fin de la file d'attente de rendu, où il arrive après la mise en page.Le bug a été reconnu par Google: code.google.com/p/android/issues/detail?id=93711#c1 Votre solution fonctionne très bien dans le temps, donc je vais l'accepter.
Toutes les idées sur la façon d'animer la durée d'attribution de l'invalidation?
Google est un temps TRÈS LONG à résoudre ce problème... maintenant, avec cette disposition, le gestionnaire est inutilisable.
Je ne suis pas exactement sûr de ce que tu veux dire par "animer la durée d'attribution de l'invalidation"? Ce que j'ai vu, c'est que, tant que le gestionnaire de la poste/solution de contournement (ci-dessus) est utilisé, la disposition appropriée des événements et des animations vont se produire. Demandez-vous si l'on peut contrôler la durée pendant laquelle l'élément augmente/réduit lorsqu'elle span compte les modifications?
OriginalL'auteur MojoTosh
Eh bien, j'ai fait de cette façon.
Créer une classe Personnalisée d' RecyclerView de Défilement Auditeur.
Espère que cela va vous aider.
OriginalL'auteur Hiren Patel