Animate Recycler View grid when number of columns change

佐手、 提交于 2019-12-10 03:54:24

问题


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();

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.

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
    }
}

回答1:


I have a solution for your problem change your toggle function to this:

  fun onToggle() {
        spanCount = if (spanCount == 2) 4 else 2
        (recyclerView.adapter!! as MyItemRecyclerViewAdapter).apply {
            span = spanCount
            notifyDataSetChanged()
        }
recyclerView.post(object:Runnable {
  public override fun run() {
     TransitionManager.beginDelayedTransition(recyclerView)
        (recyclerView.layoutManager as GridLayoutManager).spanCount = spanCount
  }
})
   }

In the above code we are first changing the viewType of recyclerView and then we are changing spanCount of GridLayoutManager on RecyclerView UI Handler Queue, so to achieve the two UI operations serially.



来源:https://stackoverflow.com/questions/51353595/animate-recycler-view-grid-when-number-of-columns-change

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!