Alaa Salah
Alaa Salah

Reputation: 1067

Android RecyclerView how to animate items only once?

I have a RecyclerViewAdapter and I would need the items to get animated when they first appear on the screen (i.e. when scrolled down) but only once, for the first time they appear, after that whenever the user scrolls up there shouldn't be any animations.

My code now works perfectly except for that last item, it always gets animated over and over again when I scroll down to it.

private Integer lastPosition = -1;

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

    holder.setIsRecyclable(false);

    // Animations
    // If the bound view wasn't previously displayed on screen, it's animated
    if (position > lastPosition) {
        holder.mImage.setAnimation(AnimationUtils.loadAnimation(context, R.anim.first_animation));
        holder.mView.setAnimation(AnimationUtils.loadAnimation(context, R.anim.second_animation));

        lastPosition = position -1;
    }
}

And if I set lastPosition = position; I only get the first few items loaded (and visible depending on screen size) animated and when I scroll down they don't get animated whatsoever.

Why is this behavior? As all examples found here for animating items with scrolling for the first time using them

lastPosition = position;

But mine fails?

My RecyclerAdapter is filterable (implements Filterable) if this would be of any essence to the issue.

Upvotes: 2

Views: 1617

Answers (2)

Hossam Ali
Hossam Ali

Reputation: 803

This is a workaround you can use in your RecyclerViewAdapter class

ArrayList<Boolean> hasAnimation;

public RecyclerViewAdapter(Context context) {
    hasAnimation=new ArrayList<>();
    this.context=context;
}

Then in onBindViewHolder method

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

    hasAnimation.add(true);

    if (hasAnimation.get(position)){
        Animation animation1= AnimationUtils.loadAnimation(context, R.anim.first_animation);
        Animation animation2= AnimationUtils.loadAnimation(context, R.anim.second_animation);
        animation1.setDuration(1000);
        animation2.setDuration(1000);
        holder.mImage.startAnimation(animation1);
        holder.mView.startAnimation(animation2);
        hasAnimation.set(position,false);
    }}

And For sure you can simplify the process with your code in animation part

    holder.mImage.setAnimation(AnimationUtils.loadAnimation(context, R.anim.first_animation));
    holder.mView.setAnimation(AnimationUtils.loadAnimation(context, R.anim.second_animation));

Hope that helps

Upvotes: 0

Dmytro Batyuk
Dmytro Batyuk

Reputation: 974

You could add additional property to the list item and check when animate and when don't:

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

    //Checking if has already animated
    if (!list.get(position).hasAnimated()) {

        //Mark this ViewHolder as animated
        list.get(position).setHasAnimated();
        holder.mImage.setAnimation(AnimationUtils.loadAnimation(context, R.anim.first_animation));
        holder.mView.setAnimation(AnimationUtils.loadAnimation(context, R.anim.second_animation));
    }
}

Upvotes: 1

Related Questions