Comment animer L'ajout ou la suppression de lignes ListView Android
dans iOS, il y a une facilité très facile et puissante pour animer l'ajout et la suppression des lignes de vue utilisables, voici un clip d'une vidéo youtube montrant l'animation par défaut. Notez comment les lignes environnantes s'effondrent 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 étaient en train de regarder quand les données ont changé.
depuis que je me suis développé sur Android je n'ai trouvé aucun équivalent possibilité d'animer des lignes individuelles dans une TableView . En appelant notifyDataSetChanged()
sur mon adaptateur, ListView met immédiatement à jour son contenu avec de nouvelles informations. J'aimerais vous montrer une simple animation d'une nouvelle ligne, poussant dans coulissantes ou lorsque les données changent, mais je ne trouve pas toutes documentées façon de le faire. Il ressemble à LayoutAnimationController pourrait tenir une clé pour obtenir ce à travailler, mais quand je mets un LayoutAnimationController sur mon ListView (similaire à LayoutAnimation2 D'ApiDemo ) et supprimer des éléments de mon adaptateur après l'affichage de la liste, les éléments disparaissent immédiatement au lieu de s'animer.
j'ai également essayé des choses comme les suivantes pour animer un élément 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);
}
cependant, les rangées entourant la rangée animée ne bougent pas la position jusqu'à ce qu'ils sautent à leur nouveau positions lorsque notifyDataSetChanged()
est appelé. Il semble que ListView ne mette pas à jour sa mise en page une fois que ses éléments ont été placés.
en écrivant ma propre implémentation/fork de ListView m'a traversé l'esprit, cela ressemble à quelque chose qui ne devrait pas être si difficile.
Merci!
14 réponses
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 l'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>
le RecyclerView
s'occupe d'ajouter, de supprimer et de ré-commander des animations!
Ce simple AndroidStudio projet dispose d'un RecyclerView
. jetez un oeil au commits :
consultez la solution Google. Voici une méthode de suppression seulement.
ListViewRemovalAnimation code du projet et vidéo démonstration
il a besoin D'Android 4.1+ (API 16). Mais nous avons 2014 à l'extérieur.
depuis ListViews
sont fortement optimisés je pense que ce n'est pas possible d'accieve. Avez-vous essayé de créer votre "ListView" par code (c'est-à-dire en gonflant vos lignes à partir du xml et en les ajoutant à un LinearLayout
) et de les animer?
avez-vous envisagé d'animer un balayage à droite? Vous pourriez faire quelque chose comme dessiner une barre blanche de plus en plus grande à travers le haut de l'élément de liste, puis le supprimer de la liste. Les autres cellules se branleraient encore, mais c'est mieux que rien.
appel listView.scheduleLayoutAnimation(); avant de changer la liste
j'ai piraté ensemble 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 rangée, mais sont inefficaces pour rétrécir réellement la vue. Ainsi, d'abord considérer ce handler:
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 liste adaptateur:
private Collection<Integer> disabledViews = new ArrayList<Integer>();
et ajouter
public boolean isEnabled(int position) {
return !disabledViews.contains(position);
}
ensuite, où que vous vouliez cacher une rangée, ajouter 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 ça! Vous pouvez modifier la vitesse de l'animation en modifiant le nombre de pixels qu'il prenne de la hauteur à la fois. Pas de réel sophistiqué, mais il fonctionne!
après avoir inséré une nouvelle ligne dans ListView, je fais simplement défiler ListView vers une nouvelle position.
ListView.smoothScrollToPosition(position);
Je ne l'ai pas essayé mais il ressemble animateLayoutChanges devrait faire ce que vous recherchez. Je le vois dans la classe ImageSwitcher, je suppose que c'est aussi dans la classe ViewSwitcher?
comme 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 requête de fonctionnalité dans android bug tracker (et si vous avez décidé de l'implémenter, n'oubliez pas de contribuer un patch ).
POUR INFORMATION, Le code source de ListView est ici .
voici le code source pour vous permettre de supprimer les lignes et de les réorganiser.
un fichier de démonstration APK est également disponible. La suppression de lignes se fait plus dans le sens de L'application Gmail de Google qui révèle une vue en bas après avoir fait glisser une vue en haut. La vue du bas peut avoir un bouton Annuler ou ce que vous voulez.
comme j'avais expliqué mon approche dans mon site j'ai partagé le lien.De toute façon l'idée est de créer des images bitmap par getdrawingcache .avoir deux bitmap et animer le bitmap inférieur pour créer l'effet mobile
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 avec des images de cette
Merci.
j'ai fait quelque chose de similaire. Une approche consiste à interpoler sur le temps d'animation la hauteur de la vue dans le temps à l'intérieur des lignes onMeasure
tout en émettant requestLayout()
pour le listView. Oui, il est peut-être préférable de le faire directement à l'intérieur du code listView, mais c'était une solution rapide (qui avait l'air bien!)
Juste partager une autre approche:
premier paramétrage de la vue Liste android: animateLayoutChanges à true :
<ListView
android:id="@+id/items_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"/>
puis j'utilise un handler pour ajouter des éléments et mettre à jour le listview avec retard:
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;
}