Dans iOS, il existe une fonction très simple et puissante pour animer l’ajout et la suppression de rangées UITableView: voici un extrait d’une vidéo youtube montrant l’animation par défaut. Notez comment les lignes environnantes se réduisent sur la ligne supprimée. Cette animation aide les utilisateurs à garder une trace de ce qui a changé dans une liste et où, dans la liste, ils regardaient lorsque les données ont été modifiées.
Depuis que je développe sur Android, je n'ai trouvé aucune possibilité équivalente d'animer des lignes individuelles dans un TableView . Lorsque vous appelez notifyDataSetChanged()
on my Adapter, ListView met immédiatement à jour son contenu avec les nouvelles informations. J'aimerais montrer une animation simple d'une nouvelle ligne qui entre ou qui disparaît lorsque les données changent, mais je ne trouve aucun moyen documenté de le faire. Il semble que LayoutAnimationController pourrait contenir une clé pour que cela fonctionne, mais lorsque je définis un LayoutAnimationController sur mon ListView (similaire à ApiDemo's LayoutAnimation2 ) et que je supprime des éléments de mon adaptateur une fois la liste affichée, les éléments disparaissent immédiatement au lieu de s'animer.
J'ai également essayé, entre autres, d'animer un élément individuel lorsqu'il est supprimé:
@Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
Animation animation = new ScaleAnimation(1, 1, 1, 0);
animation.setDuration(100);
getListView().getChildAt(position).startAnimation(animation);
l.postDelayed(new Runnable() {
public void run() {
mStringList.remove(position);
mAdapter.notifyDataSetChanged();
}
}, 100);
}
Toutefois, les lignes entourant la ligne animée ne bougent pas de position tant qu'elles ne sautent pas à leur nouvelle position lorsque notifyDataSetChanged()
est appelé. Apparemment, ListView ne met pas à jour sa mise en page une fois ses éléments placés.
Bien que l’écriture de ma propre implémentation/grille de ListView m’ait traversé l’esprit, cela semble être quelque chose qui ne devrait pas être aussi difficile.
Merci!
Animation anim = AnimationUtils.loadAnimation(
GoTransitApp.this, Android.R.anim.slide_out_right
);
anim.setDuration(500);
listView.getChildAt(index).startAnimation(anim );
new Handler().postDelayed(new Runnable() {
public void run() {
FavouritesManager.getInstance().remove(
FavouritesManager.getInstance().getTripManagerAtIndex(index)
);
populateList();
adapter.notifyDataSetChanged();
}
}, anim.getDuration());
pour une animation de haut en bas:
<set xmlns:Android="http://schemas.Android.com/apk/res/Android">
<translate Android:fromYDelta="20%p" Android:toYDelta="-20"
Android:duration="@Android:integer/config_mediumAnimTime"/>
<alpha Android:fromAlpha="0.0" Android:toAlpha="1.0"
Android:duration="@Android:integer/config_mediumAnimTime" />
</set>
La RecyclerView
se charge d'ajouter, de supprimer et de réorganiser des animations!
Ce projet AndroidStudio simple présente une RecyclerView
. jetez un coup d'œil au commits :
Jetez un coup d'oeil à la solution de Google. Voici une méthode de suppression seulement.
ListViewRemovalAnimation code du projet et Vidéo démonstration
Il nécessite Android 4.1+ (API 16). Mais nous avons 2014 à l'extérieur.
appelez listView.scheduleLayoutAnimation (); avant de changer de liste
Avez-vous envisagé d'animer un balayage vers la droite? Vous pouvez par exemple dessiner une barre blanche progressivement plus grande en haut de l’élément de la liste, puis la supprimer de la liste. Les autres cellules resteraient encore saccadées, mais ce serait mieux que rien.
Après avoir inséré une nouvelle ligne dans ListView, je viens de faire défiler le ListView vers une nouvelle position.
ListView.smoothScrollToPosition(position);
J'ai piraté une autre façon de le faire sans avoir à manipuler la vue liste. Malheureusement, les animations Android régulières semblent manipuler le contenu de la ligne, mais ne permettent pas de réduire la vue. Alors, considérons d'abord ce gestionnaire:
private Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
Bundle bundle = message.getData();
View view = listView.getChildAt(bundle.getInt("viewPosition") -
listView.getFirstVisiblePosition());
int heightToSet;
if(!bundle.containsKey("viewHeight")) {
Rect rect = new Rect();
view.getDrawingRect(rect);
heightToSet = rect.height() - 1;
} else {
heightToSet = bundle.getInt("viewHeight");
}
setViewHeight(view, heightToSet);
if(heightToSet == 1)
return;
Message nextMessage = obtainMessage();
bundle.putInt("viewHeight", (heightToSet - 5 > 0) ? heightToSet - 5 : 1);
nextMessage.setData(bundle);
sendMessage(nextMessage);
}
Ajoutez cette collection à votre adaptateur de liste:
private Collection<Integer> disabledViews = new ArrayList<Integer>();
et ajouter
public boolean isEnabled(int position) {
return !disabledViews.contains(position);
}
Ensuite, où que vous souhaitiez masquer une ligne, ajoutez ceci:
Message message = handler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putInt("viewPosition", listView.getPositionForView(view));
message.setData(bundle);
handler.sendMessage(message);
disabledViews.add(listView.getPositionForView(view));
C'est tout! Vous pouvez modifier la vitesse de l'animation en modifiant le nombre de pixels qu'il réduit en même temps. Pas vraiment sophistiqué, mais ça marche!
Puisque ListViews
sont hautement optimisés, je pense que cela n’est pas possible. Avez-vous essayé de créer votre "ListView" par code (c'est-à-dire en gonflant vos lignes à partir de xml et en les ajoutant à une LinearLayout
) et de les animer?
Étant donné qu'Android est open source, vous n'avez pas besoin de réimplémenter les optimisations de ListView. Vous pouvez récupérer le code de ListView et essayer de trouver un moyen de pirater l'animation, vous pouvez aussi ouvrir une demande de fonctionnalité dans le suivi des bugs Android (et si vous avez décidé de l'implémenter, n'oubliez pas de contribuer à patch ).
Pour votre information, le code source de ListView est here .
Je ne l'ai pas essayé, mais il semble qu'animateLayoutChanges devrait faire ce que vous cherchez. Je le vois dans la classe ImageSwitcher, je suppose que c'est aussi dans la classe ViewSwitcher?
Comme je l'avais expliqué dans mon site, j'ai partagé le lien. De toute façon, l'idée est de créer des bitmaps À l'aide de getdrawingcache. Avoir deux bitmap et d'animer le bitmap inférieur pour créer l'effet de déplacement
S'il vous plaît voir le code suivant:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View rowView, int positon, long id)
{
listView.setDrawingCacheEnabled(true);
//listView.buildDrawingCache(true);
bitmap = listView.getDrawingCache();
myBitmap1 = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), rowView.getBottom());
myBitmap2 = Bitmap.createBitmap(bitmap, 0, rowView.getBottom(), bitmap.getWidth(), bitmap.getHeight() - myBitmap1.getHeight());
listView.setDrawingCacheEnabled(false);
imgView1.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap1));
imgView2.setBackgroundDrawable(new BitmapDrawable(getResources(), myBitmap2));
imgView1.setVisibility(View.VISIBLE);
imgView2.setVisibility(View.VISIBLE);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.setMargins(0, rowView.getBottom(), 0, 0);
imgView2.setLayoutParams(lp);
TranslateAnimation transanim = new TranslateAnimation(0, 0, 0, -rowView.getHeight());
transanim.setDuration(400);
transanim.setAnimationListener(new Animation.AnimationListener()
{
public void onAnimationStart(Animation animation)
{
}
public void onAnimationRepeat(Animation animation)
{
}
public void onAnimationEnd(Animation animation)
{
imgView1.setVisibility(View.GONE);
imgView2.setVisibility(View.GONE);
}
});
array.remove(positon);
adapter.notifyDataSetChanged();
imgView2.startAnimation(transanim);
}
});
Pour comprendre en images voir ceci
Merci.
Voici le code source pour vous permettre de supprimer des lignes et de les réorganiser.
Un fichier de démonstration APK est également disponible. La suppression de lignes se fait de la manière décrite dans l'application Gmail de Google, qui révèle une vue de dessous après avoir balayé une vue de dessus. La vue inférieure peut avoir un bouton Annuler ou ce que vous voulez.
J'ai fait quelque chose de semblable à ceci. Une approche consiste à interpoler sur le temps d'animation la hauteur de la vue au fil du temps à l'intérieur des lignes onMeasure
lors de l'émission de requestLayout()
pour listView. Oui, il serait peut-être préférable de le faire directement à l'intérieur du code listView, mais c'était une solution rapide (ça avait l'air bien!)
Juste partager une autre approche:
Commencez par définir la vue en liste Android: animateLayoutChanges to true :
<ListView
Android:id="@+id/items_list"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:animateLayoutChanges="true"/>
Ensuite, j'utilise un handler pour ajouter des éléments et mettre à jour la listview avec délai:
Handler mHandler = new Handler();
//delay in milliseconds
private int mInitialDelay = 1000;
private final int DELAY_OFFSET = 1000;
public void addItem(final Integer item) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
mDataSet.add(item);
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
}
}).start();
}
}, mInitialDelay);
mInitialDelay += DELAY_OFFSET;
}