J'essaie d'animer la suppression d'un élément ListView en utilisant ceci:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, final View view, final int i, long l) {
view.animate().setDuration(500).x(-view.getWidth()).alpha(0f);
adapter.remove(tasks.get(i));
adapter.notifyDataSetChanged();
}
});
Ça ne marche pas. J'ai essentiellement suivi les conseils de la 4ème réponse du haut de ce post:
Comment animer l'ajout ou la suppression de Android Lignes ListView
Cependant, il y a des trucs drôles de dessin en cours, ou de recyclage, ou quelque chose parce que pendant que l'animation se produit, l'élément en dessous de celui qui glisse hors de l'écran est également supprimé pour une raison quelconque. La réponse que le demandeur de questions a finalement marquée comme correcte est malheureusement un RTFM vers l'ensemble de la source d'Android. J'ai parcouru la liste et je ne trouve pas le menu déroulant des notifications dans JellyBean que j'essaie d'imiter.
TIA. John
Je viens de trouver une belle solution: https://github.com/paraches/ListViewCellDeleteAnimation
Voici la vidéo: http://www.youtube.com/watch?v=bOl5MIti7n
Un grand merci à 'paraches';)
Modifier
À partir de Android version 22.0.0 le nouveau Android.support.v7.widget.RecyclerView
est disponible en tant que successeur de ListView
. Des animations standard d'ajout/suppression/mise à jour sont disponibles dès la sortie de l'emballage. Les animations des widgets sont également faciles à personnaliser ( quelques animations personnalisées ).
Je recommande fortement de passer de ListView
à RecyclerView
si vous avez besoin d'animations d'objets personnalisées.
Idée: je démarre l'animation lorsque l'utilisateur sélectionne la ligne. Une fois l'animation terminée, je supprime la ligne de l'adaptateur. Le code suivant anime la ligne sélectionnée:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ListView listView = (ListView) findViewById(R.id.listView1);
final ArrayList<String> values = new ArrayList<String>();
values.add("Android");
values.add("iPhone");
values.add("WindowsMobile");
values.add("Blackberry");
values.add("Windows7");
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
Android.R.layout.simple_list_item_1, Android.R.id.text1, values);
listView.setAdapter(adapter);
final Animation animation = AnimationUtils.loadAnimation(this,
R.anim.slide_out);
animation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
adapter.remove(adapter.getItem(selectedRow));
adapter.notifyDataSetChanged();
}
});
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(),
" " + values.get(position), Toast.LENGTH_LONG).show();
view.startAnimation(animation);
selectedRow = position;
}
});
}
fichier slide_out.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android" >
<translate
Android:fromYDelta="0%"
Android:toYDelta="100%"
Android:duration="@Android:integer/config_mediumAnimTime"/>
</set>
Comme le souligne Chet Haase dans DevBytes, https://www.youtube.com/watch?v=8MIfSxgsHIs , tout cela fonctionnera, mais n'oubliez pas d'ajouter des indicateurs transientState.
De son code:
// Here's where the problem starts - this animation will animate a View object.
// But that View may get recycled if it is animated out of the container,
// and the animation will continue to fade a view that now contains unrelated
// content.
ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, 0);
anim.setDuration(1000);
if (setTransientStateCB.isChecked()) {
// Here's the correct way to do this: if you tell a view that it has
// transientState, then ListView ill avoid recycling it until the
// transientState flag is reset.
// A different approach is to use ViewPropertyAnimator, which sets the
// transientState flag internally.
view.setHasTransientState(true);
}
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
cheeseList.remove(item);
adapter.notifyDataSetChanged();
view.setAlpha(1);
if (setTransientStateCB.isChecked()) {
view.setHasTransientState(false);
}
}
});
anim.start();
J'ai utilisé l'animation de diapositive de haut en bas pour actualiser le ListView. Voici le code que j'ai utilisé:
adapter.notifyDataSetChanged();
Animation animation = AnimationUtils.loadAnimation(
getApplication(), R.anim.slide_top_to_bottom);
getListView().startAnimation(animation);
getListView().setSelection(0);
et slide_top_to_bottom.xml (enregistrez-le dans res/anim
dossier)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:interpolator="@Android:anim/accelerate_interpolator">
<translate Android:fromYDelta="-100%" Android:toXDelta="0" Android:duration="100" />
<alpha Android:fromAlpha="0.0" Android:toAlpha="1.0" Android:duration="50" />
</set>
EDIT: Essayez ceci:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, final View view, final int i, long l) {
ValueAnimator fader = ObjectAnimator.ofFloat(view, "alpha", 1, 0);
AnimatorSet animation = new AnimatorSet();
animation.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
((AnimatorSet) animation).play(fader);
animation.setDuration(500);
animation.start();
adapter.remove(tasks.get(i));
adapter.notifyDataSetChanged();
}
});