Android ExpandableListView utilisant l'animation
j'utilise
<ExpandableListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ExpandableListView>
je veux ajouter un diaporama d'animation pour les enfants quand onclick parent . Alors, Comment puis-je faire ?
4 réponses
Mise À Jour Finale
Cela fait longtemps que je n'ai pas écrit cette réponse. Depuis lors, beaucoup de choses ont changé. Le plus grand changement est avec l'introduction de RecyclerView
qui rend l'animation d'une liste ou d'une grille facile. Je recommande fortement de passer à RecyclerView
s si vous le pouvez. Pour ceux qui ne le peuvent pas, je vais voir ce que je peux faire concernant la correction des bogues pour ma bibliothèque.
réponse Originale à cette question
en fait, je n'aime pas l'implémentation populaire d'une vue animée extensible qui utilise simplement une vue ListView avec une animation extensible parce que dans mon cas d'utilisation, chacun de mes groupes avait beaucoup d'enfants, donc il n'était pas possible d'utiliser une vue ListView normale car les vues enfant ne seront pas recyclées et l'utilisation de la mémoire sera énorme avec de mauvaises performances. Au lieu de cela, j'ai opté pour une approche beaucoup plus difficile, mais plus évolutive et souple.
j'ai étendu la classe ExpandableListView et j'ai surpassé les fonctions onCollapse et onExpand, j'ai aussi créé une sous-classe de BaseExpandableListAdapter appelé AnimatedExpandableListAdapter. À l'intérieur de l'adaptateur, j'ai surmonté la fonction getChildView et j'ai rendu la fonction finale de sorte que la fonction ne puisse pas être surmontée à nouveau. Au lieu de cela, j'ai fourni une autre fonction appelée getRealChildView pour les sous-classes à outrepasser pour fournir une vraie vue d'enfant. J'ai ensuite ajouté un drapeau d'animation à la classe et fait getchildview retourner une vue factice si le drapeau d'animation a été mis et la vue réelle si le drapeau n'a pas été mis. Maintenant, avec la mise en scène, je fais ce qui suit pour onExpand:
- placer le drapeau d'animation dans l'adaptateur et dire à l'adaptateur quel groupe est en expansion.
- Call
notifyDataSetChanged()
(oblige l'adaptateur à appelergetChildView()
pour toutes les vues sur l'écran). - l'adaptateur (en mode animation) va alors créer une vue de mannequin pour le groupe en expansion qui a une hauteur initiale de 0. L'adaptateur obtiendra alors les vues réelles de l'enfant et transmettra ces vues à la vue de mannequin.
- la vue factice commencera alors à dessiner les vues réelles de l'enfant dans sa propre fonction
onDraw()
. - l'adaptateur va lancer une boucle d'animation qui va étendre la vue de mannequin jusqu'à ce qu'elle soit de la bonne taille. Il définira également un écouteur d'animation de sorte qu'il puisse effacer le drapeau d'animation Une fois l'animation complète et appellera aussi
notifyDataSetChanged()
.
finalement avec tout cela fait, j'ai pu non seulement obtenir l'effet d'animation désiré mais aussi la performance désirée car cette méthode fonctionnera avec le groupe avec plus de 100 enfants.
pour l'animation qui s'effondre, un peu plus de travail doit être fait pour obtenir tout cela setup and running. En particulier, lorsque vous outrepassez onCollapse, vous ne voulez pas appeler la fonction du parent comme il va s'effondrer le groupe immédiatement vous ne laissant aucune chance de jouer une animation. Au lieu de ça, tu veux appeler super.onCollapse à la fin de l'animation de l'effondrement.
mise à jour:
j'ai passé un peu de temps ce week-end à réécrire ma mise en œuvre de cette vue Animéeexpandablelist et je sors le source avec un exemple d'utilisation ici: https://github.com/idunnololz/AnimatedExpandableListView /
@idunnololz solution fonctionne très bien. cependant, je voudrais ajouter un peu de code pour effondrer le groupe précédemment élargi.
private int previousGroup=-1;
listView.setOnGroupClickListener(new OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
// We call collapseGroupWithAnimation(int) and
// expandGroupWithAnimation(int) to animate group
// expansion/collapse.
if (listView.isGroupExpanded(groupPosition)) {
listView.collapseGroupWithAnimation(groupPosition);
previousGroup=-1;
} else {
listView.expandGroupWithAnimation(groupPosition);
if(previousGroup!=-1){
listView.collapseGroupWithAnimation(previousGroup);
}
previousGroup=groupPosition;
}
return true;
}
});
animateLayoutChanges adds auto-animation
<ExpandableListView
android:animateLayoutChanges="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
@idunnololz solution fonctionne bien, mais j'ai connu un comportement étrange avec ma mise en page personnalisée pour le groupe. L'expansion de l'opération n'a pas été exécutée correctement, l'effondrement cependant travaillé parfaite. J'ai importé son projet de test et il a fonctionné très bien, donc j'ai réalisé que le problème est avec ma disposition personnalisée. Cependant, quand je n'ai pas été en mesure de localiser le problème après une certaine enquête, j'ai décidé de décommenter ces lignes de code dans son AnimatedExpandListView:
if (lastGroup && Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return expandGroup(groupPos, true);
}
qui a causé le problème (mon application est destinée à Android 4.0+).