Thursday 19 July 2018

Animate Recycler View grid when number of columns change

I am using a RecyclerView with GridLayoutManager. Users can toggle the span count between 2 and 4, which would result in an animation that runs the inbuilt translate animation for each cell to it's new position. Code I have been using thus far is:

TransitionManager.beginDelayedTransition(moviesGridRecycler);
gridLayoutManager.setSpanCount(NEW_SPAN_COUNT);
adapter.notifyDataSetChanged();

enter image description here

This has been working fine for me, but now I need to have a different layout for each span count. To support this, I have 2 view types in the RecyclerView and since the view type is changed when moving to a new span count, RecyclerView is unable to see that it's the "same" content, and the default translate animation is not run.

enter image description here

If I enable layout transitions, I get view entry animations and not view position change animations. Cell views for both span count are having a width and height as match_parent and wrap_content.

As an alternative, I tried dropping the new view type all together, and just having one view type. I have a FrameLayout, which holds views for both span counts. In onBindViewHolder(), I simply toggle visibility of child views. This too results in no animations.

I followed this thread and this one, but could not resolve my issue.

Full Code:

    class ItemFragment : Fragment() {
    private var spanCount = 2
    lateinit var recyclerView: RecyclerView
    lateinit var button: Button

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_item_list, container, false)
        recyclerView = view.findViewById(R.id.listView)
        recyclerView.apply {
            adapter = MyItemRecyclerViewAdapter(DummyContent.ITEMS, spanCount)
            layoutManager = GridLayoutManager(context, spanCount)
            addItemDecoration(RecyclerGridDecoration(context))
        }
        button = view.findViewById(R.id.toggle)
        button.setOnClickListener { onToggle() }

        return view
    }

    fun onToggle() {
        spanCount = if (spanCount == 2) 4 else 2
        TransitionManager.beginDelayedTransition(recyclerView)
        (recyclerView.layoutManager as GridLayoutManager).spanCount = spanCount
        (recyclerView.adapter!! as MyItemRecyclerViewAdapter).apply {
            span = spanCount
            notifyDataSetChanged()
        }
    }

}



class MyItemRecyclerViewAdapter(
        private val mValues: List<DummyItem>,
        var span: Int)
    : RecyclerView.Adapter<MyItemRecyclerViewAdapter.ViewHolder>() {


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        if (viewType == 2) {
            val view = LayoutInflater.from(parent.context)
                    .inflate(R.layout.items_two, parent, false)
            return TwoViewHolder(view)
        } else {
            val view = LayoutInflater.from(parent.context)
                    .inflate(R.layout.items_four, parent, false)
            return FourViewHolder(view)
        }

    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = mValues[position]
        if (holder is TwoViewHolder) {
            holder.textTwo.text = item.content
        } else if (holder is FourViewHolder) {
            holder.textFour.text = item.content
        }
    }

    override fun getItemCount(): Int = mValues.size

    abstract inner class ViewHolder(mView: View) : RecyclerView.ViewHolder(mView)

    inner class TwoViewHolder(mView: View) : ViewHolder(mView) {
        val image: ImageView = mView.imageTwo
        val textTwo: TextView = mView.textTwo

    }

    inner class FourViewHolder(mView: View) : ViewHolder(mView) {
        val textFour: TextView = mView.textFour
    }

    override fun getItemViewType(position: Int): Int {
        return span
    }
}



from Animate Recycler View grid when number of columns change

No comments:

Post a Comment