ejemplo - custom listview android studio
Anima la eliminaciĆ³n de un elemento ListView (4)
Estoy intentando animar la eliminación de un elemento ListView usando esto:
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();
}
});
No funciona. Básicamente, seguí el consejo de la cuarta respuesta desde la parte superior de esta publicación:
Cómo animar la adición o la eliminación de las filas de Android ListView
Sin embargo, hay algunas cosas graciosas de dibujo en curso, o reciclaje, o algo así porque, mientras se produce la animación, el elemento debajo del que se desliza fuera de la pantalla también se elimina por alguna razón. La respuesta que la pregunta asker finalmente marcó como correcta es desafortunadamente un RTFM hacia toda la fuente de Android. Miré por allí y no puedo encontrar las notificaciones desplegables en JellyBean que estoy tratando de emular.
TIA. John
Acabo de encontrar una hermosa solución: https://github.com/paraches/ListViewCellDeleteAnimation
Aquí hay un video: http://www.youtube.com/watch?v=bOl5MIti7n0
Muchas gracias a ''paraches'';)
Editar
A partir de la versión de Android 22.0.0, el nuevo android.support.v7.widget.RecyclerView
está disponible como un sucesor de ListView
. Las animaciones estándar de agregar / quitar / actualizar están disponibles de manera inmediata. Las animaciones de widget también son fáciles de personalizar ( pocas animaciones personalizadas ).
Recomiendo cambiar de ListView
a RecyclerView
si necesita animaciones de elementos personalizados.
Como señala Chet Haase en DevBytes, https://www.youtube.com/watch?v=8MIfSxgsHIs , todo esto funcionará, pero no olvides agregar flags de transientState.
De su código:
// 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();
He utilizado la animación de diapositivas de arriba a abajo al actualizar ListView. Aquí está el código que utilicé:
adapter.notifyDataSetChanged();
Animation animation = AnimationUtils.loadAnimation(
getApplication(), R.anim.slide_top_to_bottom);
getListView().startAnimation(animation);
getListView().setSelection(0);
y slide_top_to_bottom.xml (guárdelo dentro de la carpeta res/anim
)
<?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>
EDITAR: Prueba esto:
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();
}
});
Idea: inicio la animación cuando el usuario selecciona la fila. Cuando la animación se completa, elimino la fila del adaptador. El siguiente código anima la fila seleccionada:
@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;
}
});
}
archivo 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>