列数更改时对Recycler View网格进行动画处理 [英] Animate Recycler View grid when number of columns change

查看:101
本文介绍了列数更改时对Recycler View网格进行动画处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将RecyclerViewGridLayoutManager一起使用.用户可以在2到4之间切换跨度计数,这将生成一个动画,该动画将每个单元格的内置转换动画运行到新位置.到目前为止,我一直在使用的代码是:

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

这对我来说很好,但是现在我需要为每个跨度计数使用不同的布局.为此,我在RecyclerView中有2种视图类型,并且由于在移动到新的跨度计数时视图类型已更改,因此RecyclerView无法看到它是相同"的内容,并且默认的转换动画是不跑.

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.

如果启用布局过渡,则将获得视图输入动画,而不是视图位置更改动画.两个跨度计数的单元格视图的宽度和高度分别为match_parentwrap_content.

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.

作为一种选择,我尝试将新的视图类型全部放在一起,而只使用一种视图类型.我有一个FrameLayout,其中包含两个跨度计数的视图.在onBindViewHolder()中,我只是切换子视图的可见性.这也不会产生动画.

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.

完整代码:

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

推荐答案

对于您的问题,我有一个解决方案,请将您的切换功能更改为:

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

在上面的代码中,我们首先更改recyclerView的viewType,然后更改RecyclerView UI Handler Queue上GridLayoutManager的spanCount,以便依次实现两个UI操作.

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.

这篇关于列数更改时对Recycler View网格进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆