yazan sayed
yazan sayed

Reputation: 1139

Animating recyclerView items

I'm applying some AnimatorSet to the items of a recyclerView,

recyclerView adapter:

class MyAdapter(...) : 
androidx.recyclerview.widget.RecyclerView.Adapter<MyAdapter.ViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, p1: Int): ViewHolder {
    return ViewHolder(...)
    }

override fun onBindViewHolder(p0: ViewHolder, p1: Int) {
    p0.bind(...)
    }


inner class ViewHolder(itemView: View,...) : 
androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) {

fun bind(...) {
        ...
        animateItemView(itemView)
        ...
}
}
}

animateItemView function

        fun animateItemView(itemView: View) {
        //hide the itemView
        itemView.alpha = 0f

        //moving the itemView down 400f
        ObjectAnimator.ofFloat(itemView, "translationY", 0f, 400f)
            .apply { duration = 1L }.start()

        //show
        //itemView.alpha = 1f

        //moving the itemView up 400f
        val translateUp = ObjectAnimator.ofFloat(itemView, "translationY", 400f, 0f)
            .apply {
                duration = 1000L
                interpolator = AnticipateOvershootInterpolator(2f)
            }

        //animating alpha
        val fade = ValueAnimator.ofFloat(0f, 1f)
            .apply {
                addUpdateListener {
                    itemView.alpha = this.animatedValue as Float
                }
                duration = 400L
            }

        //applying
        AnimatorSet().apply { playTogether(translateUp, fade) }.start()


    }

result:

enter image description here

surly when scrolling upwards the itemView still slides up, is there a way to apply different animation for scrolling up/down ,, or what is a better approach ?

Upvotes: 0

Views: 3801

Answers (1)

Pawel
Pawel

Reputation: 17258

I don't know why everyone is fascinated about putting everything into RecyclerView.Adapter.

You can inject this animation into RecyclerView.LayoutManager instead as it is aware of exact moment and position where views are added:

open class FadeInLinearLayoutManager : LinearLayoutManager {
    constructor(context: Context?) : super(context)
    constructor(context: Context?, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    private val enterInterpolator = AnticipateOvershootInterpolator(2f)

    override fun addView(child: View, index: Int) {
        super.addView(child, index)
        val h = 400f
        // if index == 0 item is added on top if -1 it's on the bottom
        child.translationY = if(index == 0) -h else h
        // begin animation when view is laid out
        child.alpha = 0.3f
        child.animate().translationY(0f).alpha(1f)
                .setInterpolator(enterInterpolator)
                .setDuration(1000L)
    }
}

Then use it as your layout manager:

recyclerView.layoutManager = FadeInLinearLayoutManager(context)

Upvotes: 3

Related Questions