I have a RecyclerView with many items that are basically some CardView.
Those cards have a supporting text in the middle of their bodies, which has the visibility set to GONE by default, and it's made VISIBLE when I click the arrow on the right of the card.
I'm trying to animate the card while the text is revealed and while it's collapsed.
The picture below shows the expanded card and the collapsed one:

The CardView layout (I've removed some parts for readability):
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="3dp"
card_view:cardElevation="4dp"
card_view:cardUseCompatPadding="true"
android:id="@+id/root">
<LinearLayout
android:id="@+id/item_ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="@dimen/activity_vertical_margin">
<!-- The header with the title and the item -->
<TextView
android:id="@+id/body_content"
style="@style/TextAppearance.AppCompat.Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:layout_marginBottom="8dp"
android:text="@string/about_page_description"
android:textColor="@color/secondaryText"
android:visibility="gone"/>
<!-- The divider, and the footer with the timestamp -->
</LinearLayout>
</android.support.v7.widget.CardView>
The animations is working when the card is expanding and revealing the body TextView, however, when I try to collapse it back, the cards below the animated one overlaps the first one.
Example:

I've already asked a similar question about this behavior here before, but that solution is not working for a TextView in the middle of the card.
The code that's responsible for the animation part is inside the RecyclerView adapter. The arrow has a click listener that calls the method below:
private fun toggleVisibility() {
if (bodyContent.visibility == View.GONE || bodyContent.visibility == View.INVISIBLE) {
btSeeMore.animate().rotation(180f).start()
TransitionManager.beginDelayedTransition(root, AutoTransition())
bodyContent.visibility = View.VISIBLE
}
else {
btSeeMore.animate().rotation(0f).start()
TransitionManager.beginDelayedTransition(root, AutoTransition())
bodyContent.visibility = View.GONE
}
}
Where root is my CardView.
I've also tried to use the LinearLayout instead of the card itself for the delayed transition, but that didn't work either.
How can I achieve that behavior for my layout?
You will have to perform the transition on the RecyclerView, not on individual items. Otherwise, the RecyclerView layout changes aren't taken into account by the auto transition, because it will only look at what changes in that very child view, even though in fact, other ViewHolders are indirectly affected (layout parameters are changing).
So, instead of passing "root" (the item view) to TransitionManager#beginDelayedTransition, pass a reference to your RecyclerView
You have to apply TransitionManager.beginDelayedTransition on the root view where the cardview is contained
You have to remove android:animateLayoutChanges="true" from all over the layout
TransitionManager.beginDelayedTransition(the_root_view_where_card_view_exist, new AutoTransition());
RecyclerView does behave oddly if his items are resizing outside RecyclerViews callbacks. Try using adapter.notifyItemChanged(position, payload) and updating the item then:
Replace adapter's onclick with this:
adapter.notifyItemChanged(adapterPosition, true) // needs adapter reference, can use more meaningful payload
Then inside of your adapter:
override fun onBindViewHolder(holder: Holder, position: Int, payloads: List<Any>) {
if (payloads.isEmpty())
onBindViewHolder(holder, position)
else
holder.toggleVisibility()
}
You can also see what happens when running delayedTransition on LinearLayout instead of Card itself.
This won't be perfect, but it will trigger animation of following items instead of them jumping and clipping.
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