Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CardView within RecyclerView: animation while populating

I have a recycled view which is populated with CardView layouts. I've noticed that in many apps, these items have a nice animated entrance rather than abruptly appearing as they currently do in my application. An example of what I'm trying to achieve is shown below: enter image description here

How would I use my swipeRefreshListener/adapter to trigger this animation? How would I implement this through my adapter?

Note: I need this animation to also be triggered when the RecyclerView is first populated with the CardView items, and the data they contain.

My RecyclerView's adapter is shown below:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {

private String[] mDataset;
private String[] mClassDataset;
private int lastPosition = -1;
private Context context;

View view;


public static class ViewHolder extends RecyclerView.ViewHolder {

    public TextView mTextView;
    public TextView mClassDataView;
    CardView container;


    public ViewHolder(View itemView) {
        super(itemView);
        mTextView = (TextView)itemView.findViewById(R.id.grade);
        mClassDataView = (TextView)itemView.findViewById(R.id.class_name);
        container = (CardView)itemView.findViewById(R.id.card_view);
    }
}

public RecyclerAdapter(String[] myDataset, String[] classData, Context context) {
    mDataset = myDataset;
    mClassDataset = classData;
    this.context = context;

}

@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View v = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_item, parent, false);

    ViewHolder vh = new ViewHolder(v);

    view = v;

    return vh;
}

@Override
public int getItemCount() {
    return mClassDataset.length;
}

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


    if (mDataset.length < mClassDataset.length) {

        holder.mTextView.setText("N/A");
        holder.mClassDataView.setText(mClassDataset[position]);

        if (mClassDataset[position].equals("N/A")) {

        }

    } else {
        holder.mTextView.setText(mDataset[position]);
        holder.mClassDataView.setText(mClassDataset[position]);
    }

    for (int i = 0; i < getItemCount(); i++) {

        animate(view, i);

    }
}

private void animate(final View view, final int position){

        Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
        view.startAnimation(animation);
        lastPosition = position;

    }

}

The animation is currently working, however the thing is the items are being animated all at once. I tried iterating through the items by creating a custom getChild() method, but that didn't work. Somehow I need to access/animate each child individually and possibly set a delay between each animation. However, I'm not sure how exactly I can accomplish this. I know I can use a Handler to set delay, but accessing each child is a problem.

like image 273
mlz7 Avatar asked Aug 27 '15 02:08

mlz7


People also ask

How do you animate items in RecyclerView?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Add the following code to res/layout/activity_main. xml. Step 3 − Add the following code to res/anim/down_to_up.

Can we use CardView without RecyclerView?

Yes, You can use cardview as menu item but you should use layout instead of menu. You need to implement individual click for them.

What is difference between CardView and RecyclerView?

You can use the RecyclerView to display a list of items or objects, and the CardView to display some data of that object.

How do I customize my CardView?

Customized CardView First, add a CardView dependency to the application-level build. gradle file. Then create a drawable background for the cards. For that, create a new drawable resource file inside the drawable folder.


2 Answers

Use this custom class of RecyclerView, it behaves like the app that you posted its screenshot (Reddit Relay), it prevents scrolling while animating first items. You may want to custom the animation as you want.

package net.leolink.android.testrecyclerviewentranceanimation;  import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View;  /**  * @author Leo on 2015/09/03  */ public class MyRecyclerView extends RecyclerView {     private boolean mScrollable;      public MyRecyclerView(Context context) {         this(context, null);     }      public MyRecyclerView(Context context, AttributeSet attrs) {         this(context, attrs, 0);     }      public MyRecyclerView(Context context, AttributeSet attrs, int defStyle) {         super(context, attrs, defStyle);         mScrollable = false;     }      @Override     public boolean dispatchTouchEvent(MotionEvent ev) {         return !mScrollable || super.dispatchTouchEvent(ev);     }      @Override     protected void onLayout(boolean changed, int l, int t, int r, int b) {         super.onLayout(changed, l, t, r, b);         for (int i = 0; i < getChildCount(); i++) {             animate(getChildAt(i), i);              if (i == getChildCount() - 1) {                 getHandler().postDelayed(new Runnable() {                     @Override                     public void run() {                         mScrollable = true;                     }                 }, i * 100);             }         }     }      private void animate(View view, final int pos) {         view.animate().cancel();         view.setTranslationY(100);         view.setAlpha(0);         view.animate().alpha(1.0f).translationY(0).setDuration(300).setStartDelay(pos * 100);     } } 


DEMO

Demo

like image 170
Leo Avatar answered Sep 23 '22 14:09

Leo


First define the animation:

<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0"
    android:duration="300"/>
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
    android:duration="300" />
</set>

Then set it in your adapter:

    @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.container, 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.push_left_in);
        viewToAnimate.startAnimation(animation);
        lastPosition = position;
    }
}

Referenced from: RecyclerView : How to create insert animation effect?

like image 37
LonelyIdiot Avatar answered Sep 21 '22 14:09

LonelyIdiot