tipos - Cómo animar la adición o eliminación de filas ListView de Android
sharedpreferences listview android (14)
En iOS, hay una facilidad muy fácil y poderosa para animar la adición y eliminación de filas de UITableView, aquí hay un clip de un video de youtube que muestra la animación predeterminada. Observe cómo las filas circundantes se colapsan en la fila eliminada. Esta animación ayuda a los usuarios a realizar un seguimiento de lo que cambió en una lista y en qué lugar de la lista estaban mirando cuando los datos cambiaron.
Desde que he estado desarrollando en Android, no he encontrado ninguna facilidad equivalente para animar filas individuales en un TableView . Al llamar a notifyDataSetChanged()
en mi Adaptador, ListView actualiza inmediatamente su contenido con nueva información. Me gustaría mostrar una animación simple de una nueva fila presionando o deslizándose cuando los datos cambian, pero no puedo encontrar ninguna forma documentada de hacerlo. Parece que LayoutAnimationController podría tener una clave para hacer que esto funcione, pero cuando configuro un LayoutAnimationController en mi ListView (similar a ApiDemo''s LayoutAnimation2 ) y elimino elementos de mi adaptador una vez que la lista se muestra, los elementos desaparecen inmediatamente en lugar de animarse. .
También he intentado cosas como las siguientes para animar un elemento individual cuando se elimina:
@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);
}
Sin embargo, las filas que rodean la fila animada no se mueven de posición hasta que saltan a sus nuevas posiciones cuando se llama a notifyDataSetChanged()
. Parece que ListView no actualiza su diseño una vez que se han colocado sus elementos.
Mientras escribo mi propia implementación / bifurcación de ListView ha pasado por mi mente, esto parece algo que no debería ser tan difícil.
¡Gracias!
¡ RecyclerView
se encarga de agregar, eliminar y reordenar animaciones!
Este proyecto simple de AndroidStudio presenta un RecyclerView
. Echa un vistazo a los commits :
- Compromiso de la clásica aplicación de Android Hello World.
- commit, agregando un RecyclerView al proyecto (contenido no dinámico)
- confirme, agregando funcionalidad para modificar el contenido de RecyclerView en tiempo de ejecución (pero sin animaciones)
- y finalmente ... cometer agregando animaciones al RecyclerView
¿Has considerado animar un barrido a la derecha? Podría hacer algo como dibujar una barra blanca progresivamente más grande en la parte superior del elemento de la lista y luego eliminarlo de la lista. Las otras células todavía se sacudían en su lugar, pero sería mejor que nada.
Aquí está el código fuente para permitirte eliminar filas y reordenarlas.
Un archivo APK demo también está disponible. La eliminación de filas se realiza más a lo largo de las líneas de la aplicación Gmail de Google que revela una vista inferior después de deslizar una vista superior. La vista inferior puede tener un botón Deshacer o lo que quieras.
Como expliqué mi enfoque en mi sitio, compartí el enlace. De todos modos, la idea es crear mapas de bits con getdrawingcache. Tener dos mapas de bits y animar el mapa de bits inferior para crear el efecto de movimiento
Por favor vea el siguiente código:
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);
}
});
Para entender con imágenes ve esto.
Gracias.
Dado que ListViews
están altamente optimizados, creo que esto no es posible acceder. ¿Ha intentado crear su "ListView" por código (es decir, inflando sus filas de xml y LinearLayout
a un LinearLayout
) y LinearLayout
?
Dado que Android es de código abierto, en realidad no necesita volver a implementar las optimizaciones de ListView. Puede capturar el código de ListView e intentar encontrar una manera de piratear la animación, también puede abrir una solicitud de función en el rastreador de errores de Android (y si decide implementarlo, no olvide contribuir con un parche ).
Para su información, el código fuente de ListView está here .
Después de insertar una nueva fila en ListView, simplemente muevo el ListView a una nueva posición.
ListView.smoothScrollToPosition(position);
Echa un vistazo a la solución de Google. Aquí es sólo un método de eliminación.
ListViewRemovalAnimation código de proyecto y demostración de Video
Necesita Android 4.1+ (API 16). Pero tenemos 2014 fuera.
Hacké juntos otra forma de hacerlo sin tener que manipular la vista de lista. Desafortunadamente, las animaciones regulares de Android parecen manipular el contenido de la fila, pero no son efectivas para reducir realmente la vista. Entonces, primero considere este controlador:
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);
}
Agregue esta colección a su adaptador de lista:
private Collection<Integer> disabledViews = new ArrayList<Integer>();
y añadir
public boolean isEnabled(int position) {
return !disabledViews.contains(position);
}
A continuación, donde quiera que desee ocultar una fila, agregue esto:
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));
¡Eso es! Puede cambiar la velocidad de la animación modificando la cantidad de píxeles que reduce la altura a la vez. No es realmente sofisticado, pero funciona!
He hecho algo parecido a esto. Un enfoque es interpolar durante el tiempo de animación la altura de la vista a lo largo del tiempo dentro de las filas en onMeasure
mientras se emite requestLayout()
para listView. Sí, puede ser mejor hacerlo dentro del código listView directamente, pero fue una solución rápida (¡se veía bien!)
No lo he probado, pero parece que animateLayoutChanges debería hacer lo que estás buscando. Lo veo en la clase ImageSwitcher, ¿asumo que también está en la clase ViewSwitcher?
Solo compartiendo otro enfoque:
Primero establece el android: animateLayoutChanges de la vista de lista en true :
<ListView
android:id="@+id/items_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"/>
Luego uso un controlador para agregar elementos y actualizar la vista de lista con retraso:
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;
}
llamada listView.scheduleLayoutAnimation (); antes de cambiar la lista
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());
para la animación de arriba a abajo use:
<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>