更改列数时如何使Recycler View网格动画化

9

我正在使用RecyclerViewGridLayoutManager。用户可以在2和4之间切换跨度,这会导致动画运行每个单元格到其新位置的内置翻译动画。迄今为止,我一直在使用以下代码:

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

在此输入图片描述

这个对我来说一直很好用,但现在我需要为每个span count设置不同的布局。为了支持这一点,在RecyclerView中我有2种视图类型, 因为当移动到新的 span count 时,视图类型会更改,RecyclerView无法看到它是“相同”的内容,因此默认的翻译动画没有运行。

在此输入图片描述

如果启用布局转换,则只能获得视图入口动画而不是视图位置变化动画。两个span count 的单元格视图的宽度和高度都为 match_parentwrap_content

作为替代方案,我尝试放弃全新的视图类型,只使用一个视图类型。我有一个FrameLayout,它保存了两个span count 的视图。在onBindViewHolder()中,我只需切换子视图的可见性。这也导致没有任何动画。

我遵循了这个线程这个线程,但无法解决我的问题。

完整代码:

    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个回答

2
我有一个解决方案,可以解决你的问题。将你的切换函数改为以下内容:
  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处理程序队列上更改GridLayoutManager的spanCount,以便实现两个UI操作的串行。

我有一个标题,其跨度计数与其他单元格不同。采用这种方法,当在设置spanCount之前调用notifyDataSetChanged时,标题无法获得正确的跨度计数。 - dev
你能分享一下你的屏幕,包括适配器的头部和代码吗? - Karan Kalsi
@KaranKalsi 谢谢你的回复。在第一部分中,你是否期望这些项目在两种视图类型之间使用过渡动画进行切换?对我来说,它们会立即改变,而我希望它们在移动到新列时能够以其新布局进行转换。 - NeilS
@KaranKalsi 非常抱歉回复晚了。我这周去度假了,所以没能更早地测试。标题不起作用是我的代码中的另一个错误,现在已经修复好了。谢谢! - dev
@Jaguar 非常欢迎 - Karan Kalsi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接