wasabeef recyclerview recycler itemanimator item best animators animations android android-animation android-recyclerview

android - itemanimator - Animate RecyclerView cuando se desplaza



recyclerview set item animator (3)

¿Hay alguna forma de animar los elementos de un RecyclerView cuando lo desplazo?

DefaultItemAnimator un vistazo a DefaultItemAnimator y RecyclerView.ItemAnimator , pero parece que las animaciones solo se llaman si el conjunto de datos ha cambiado, DefaultItemAnimator si me equivoco.

Estoy un poco confundido acerca de RecyclerView.ItemAnimator.animateMove() cuando se llama? Puse algunos puntos de interrupción en esa clase, pero ninguno de ellos detiene mi aplicación.

Sin embargo, volviendo a mi pregunta, ¿cómo puedo animar el RecyclerView? Quiero que algunos elementos tengan otra opacidad, depende de algunas reglas personalizadas.

Hice un poco más de resolución, parece que el movimiento de animación es exactamente lo que estoy buscando. Estos métodos se llaman desde dispatchLayout() . Aquí está el javadoc de ese método:

Envuelva alrededor de layoutChildren () que maneja los cambios de animación causados ​​por el diseño. Las animaciones se basan en el supuesto de que hay cinco tipos diferentes de elementos en juego:
PERSISTENTE: los elementos son visibles antes y después del diseño
QUITADO: los elementos eran visibles antes del diseño y fueron eliminados por la aplicación
AÑADIDO: los elementos no existían antes del diseño y fueron agregados por la aplicación
DESAPARICIÓN: los elementos existen en el conjunto de datos anterior / posterior, pero se modificaron de visibles a no visibles en el proceso de diseño (se eliminaron de la pantalla como efecto secundario de otros cambios)
APARIENDO: los elementos existen en el conjunto de datos anterior / posterior, pero se cambiaron de no visibles a visibles en el proceso de diseño (se movieron en la pantalla como un efecto secundario de otros cambios)
El enfoque general determina qué elementos existen antes / después del diseño e infiere uno de los cinco estados anteriores para cada uno de los elementos. Entonces las animaciones se configuran en consecuencia:
Las vistas PERSISTENTES se mueven ({@link ItemAnimator # animateMove (ViewHolder, int, int, int, int)}) Se eliminan las vistas QUITADAS ({@link ItemAnimator # animateRemove (ViewHolder)})
Se agregan vistas agregadas ({@link ItemAnimator # animateAdd (ViewHolder)})
Las vistas que desaparecen se mueven fuera de la pantalla
Las vistas que aparecen se mueven en la pantalla

Hasta ahora estoy buscando PERSISTENTE, DESAPARECIDO y APARIENDO, pero los métodos nunca se llaman debido a esta línea aquí:

boolean animateChangesSimple = mItemAnimator != null && mItemsAddedOrRemoved && !mItemsChanged;

mItemsAddedOrRemoved es simplemente siempre falso, por lo que nunca se llega a esa devolución de llamada. ¿Alguna idea de cómo configurar la bandera de conjunto correctamente?


La buena solución es animar el soporte en el adaptador en el método onBindViewHolder . Fragmento tomado del proyecto de prueba de materiales Slidenerd:

@Override public void onBindViewHolder(ViewHolderBoxOffice holder, int position) { Movie currentMovie = mListMovies.get(position); //one or more fields of the Movie object may be null since they are fetched from the web holder.movieTitle.setText(currentMovie.getTitle()); //retrieved date may be null Date movieReleaseDate = currentMovie.getReleaseDateTheater(); if (movieReleaseDate != null) { String formattedDate = mFormatter.format(movieReleaseDate); holder.movieReleaseDate.setText(formattedDate); } else { holder.movieReleaseDate.setText(Constants.NA); } int audienceScore = currentMovie.getAudienceScore(); if (audienceScore == -1) { holder.movieAudienceScore.setRating(0.0F); holder.movieAudienceScore.setAlpha(0.5F); } else { holder.movieAudienceScore.setRating(audienceScore / 20.0F); holder.movieAudienceScore.setAlpha(1.0F); } if (position > mPreviousPosition) { AnimationUtils.animateSunblind(holder, true); } else { AnimationUtils.animateSunblind(holder, false); } mPreviousPosition = position;

aqui hay un link


Lo hice de esta manera. Podría ayudar a alguien. No sé si es la mejor manera de hacerlo pero funciona bien para mí.

ACTUALIZACIÓN: para corregir el comportamiento de desplazamiento rápido, anule el método onViewDetachedFromWindow del adaptador y llame a clearAnimation en la vista animada (en este caso, holder.itemView.clearAnimation() ).

up_from_bottom.xml

<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="@android:anim/decelerate_interpolator"> <translate android:fromXDelta="0%" android:toXDelta="0%" android:fromYDelta="100%" android:toYDelta="0%" android:duration="400" /> </set>

down_from_top.xml

<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="@android:anim/decelerate_interpolator"> <translate android:fromXDelta="0%" android:toXDelta="0%" android:fromYDelta="-100%" android:toYDelta="0%" android:duration="400" /> </set>

Y finalmente ponga este código en onBindViewHolder de recyclerView . Cree un campo llamado lastPosition e inicialícelo en -1.

Animation animation = AnimationUtils.loadAnimation(context, (position > lastPosition) ? R.anim.up_from_bottom : R.anim.down_from_top); holder.itemView.startAnimation(animation); lastPosition = position;


Terminé usando un OnScrollListener y animándolo en un método animate() . En mi caso, el código toma solo 2 ms, por lo que no hay problema para los 60 fps.

recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(int newState) { if(newState == RecyclerView.SCROLL_STATE_IDLE) { // special handler to avoid displaying half elements scrollToNext(); } animate(); } @Override public void onScrolled(int dx, int dy) { animate(); } });