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
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With