Cómo animar elementos de RecyclerView cuando aparecen
¿Cómo puedo animar los elementos de RecyclerView cuando aparecen?
El animador de elementos predeterminado solo se anima cuando se agregan o eliminan datos después de que se hayan configurado los datos del reciclador.
¿Cómo se puede lograr esto?
EDITAR :
Según la documentación de ItemAnimator :
Esta clase define las animaciones que tienen lugar en los elementos a medida que se realizan cambios en el adaptador.
Entonces, a menos que agregue sus elementos uno por uno RecyclerView
y actualice la vista en cada iteración, no creo que ItemAnimator
sea la solución a sus necesidades.
Así es como puedes animar los RecyclerView
elementos cuando aparecen usando un CustomAdapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder>
{
private Context context;
// The items to display in your RecyclerView
private ArrayList<String> items;
// Allows to remember the last item shown on screen
private int lastPosition = -1;
public static class ViewHolder extends RecyclerView.ViewHolder
{
TextView text;
// You need to retrieve the container (ie the root ViewGroup from your custom_item_layout)
// It's the view that will be animated
FrameLayout container;
public ViewHolder(View itemView)
{
super(itemView);
container = (FrameLayout) itemView.findViewById(R.id.item_layout_container);
text = (TextView) itemView.findViewById(R.id.item_layout_text);
}
}
public CustomAdapter(ArrayList<String> items, Context context)
{
this.items = items;
this.context = context;
}
@Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_item_layout, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.text.setText(items.get(position));
// Here you apply the animation when the view is bound
setAnimation(holder.itemView, position);
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
}
Y tu custom_item_layout se vería así:
<FrameLayout
android:id="@+id/item_layout_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item_layout_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"/>
</FrameLayout>
Para obtener más información sobre CustomAdapters y RecyclerView
, consulte esta capacitación en la documentación oficial .
Problemas con el desplazamiento rápido
El uso de este método podría causar problemas con el desplazamiento rápido. La vista podría reutilizarse mientras se realiza la animación. Para evitarlo es recomendable borrar la animación cuando se despegue.
@Override
public void onViewDetachedFromWindow(final RecyclerView.ViewHolder holder)
{
((CustomViewHolder)holder).clearAnimation();
}
En CustomViewHolder:
public void clearAnimation()
{
mRootLayout.clearAnimation();
}
Antigua respuesta:
Eche un vistazo al repositorio de Gabriele Mariotti , estoy bastante seguro de que encontrará lo que necesita. Proporciona ItemAnimators simples para RecyclerView, como SlideInItemAnimator o SlideScaleItemAnimator.
Hecho simple solo con XML
Visitar enlace esencial
res/anim/layout_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/item_animation_fall_down"
android:animationOrder="normal"
android:delay="15%" />
res/anim/item_animation_fall_down.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500">
<translate
android:fromYDelta="-20%"
android:toYDelta="0"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:interpolator="@android:anim/decelerate_interpolator"
/>
<scale
android:fromXScale="105%"
android:fromYScale="105%"
android:toXScale="100%"
android:toYScale="100%"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/decelerate_interpolator"
/>
</set>
Úselo en diseños y vistas de reciclaje como:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_animation"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
Animé la aparición gradual de Recyclerview
elementos cuando aparecen por primera vez, como se muestra en el código siguiente. Quizás esto sea de utilidad para alguien.
private final static int FADE_DURATION = 1000; //FADE_DURATION in milliseconds
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getTextView().setText("some text");
// Set the view to fade in
setFadeAnimation(holder.itemView);
}
private void setFadeAnimation(View view) {
AlphaAnimation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
También puedes reemplazarlo setFadeAnimation()
con lo siguiente setScaleAnimation()
para animar la apariencia de los elementos escalándolos desde un punto:
private void setScaleAnimation(View view) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(FADE_DURATION);
view.startAnimation(anim);
}
El código anterior tiene algunos defectos en la medida en que cuando se desplaza, los RecyclerView
elementos siempre se desvanecen o escalan. Si lo desea, puede agregar código para permitir que la animación ocurra cuando se RecyclerView
crea por primera vez el fragmento o actividad que contiene (por ejemplo, obtener la hora del sistema en la creación y solo permitir la animación durante los primeros milisegundos de FADE_DURATION).
Creé una animación a partir de la respuesta de pbm con poco modification
para que la animación se ejecutara solo una vez.
en otras palabras elAnimation appear with you scroll down only
private int lastPosition = -1;
private void setAnimation(View viewToAnimate, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition) {
ScaleAnimation anim = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimate.startAnimation(anim);
lastPosition = position;
}
}
y en onBindViewHolder
llamar a la función
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.getTextView().setText("some text");
// call Animation function
setAnimation(holder.itemView, position);
}
Puedes agregar un android:layoutAnimation="@anim/rv_item_animation"
atributo RecyclerView
como este:
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down"
/>
gracias por el excelente artículo aquí: https://proandroiddev.com/enter-animation-using-recyclerview-and-layoutanimation-part-1-list-75a874a5d213