Cómo animar elementos de RecyclerView cuando aparecen

Resuelto PaulNunezM asked hace 54 años • 11 respuestas

¿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?

PaulNunezM avatar Jan 01 '70 08:01 PaulNunezM
Aceptado

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 RecyclerViewy actualice la vista en cada iteración, no creo que ItemAnimatorsea la solución a sus necesidades.

Así es como puedes animar los RecyclerViewelementos 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.

MathieuMaree avatar Nov 05 '2014 01:11 MathieuMaree

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" />
iamnaran avatar Feb 13 '2019 11:02 iamnaran

Animé la aparición gradual de Recyclerviewelementos 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 RecyclerViewelementos siempre se desvanecen o escalan. Si lo desea, puede agregar código para permitir que la animación ocurra cuando se RecyclerViewcrea 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).

pbm avatar Jan 27 '2016 07:01 pbm

Creé una animación a partir de la respuesta de pbm con poco modificationpara 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 onBindViewHolderllamar a la función

@Override
public void onBindViewHolder(ViewHolder holder, int position) {

holder.getTextView().setText("some text");

// call Animation function
setAnimation(holder.itemView, position);            
}
Basheer AL-MOMANI avatar Apr 11 '2016 10:04 Basheer AL-MOMANI

Puedes agregar un android:layoutAnimation="@anim/rv_item_animation"atributo RecyclerViewcomo 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

Pavel Biryukov avatar Feb 20 '2018 09:02 Pavel Biryukov