Collapsing CardView inside RecyclerView when animating
Asked Answered
M

1

22

What I'm trying to do

I have a CardView with a supporting text on the bottom that is GONE by default. I want to make this section of the card visible only when the user clicks the "action arrow", as shown on the image below:

Expand Arrow

I know I can achieve that by simply setting that View visibility to VISIBLE, but I also want to animate the expand and the collapse events.

The problem and what I've tried so far

To do that I've used the android:animateLayoutChanges="true" property on my CardView xml, and it works just fine when it's expanding. But once I click on the arrow again to collapse the supporting text, the card below overlaps the card I've clicked during the animation. How can I avoid this overlapping?

EDIT: I know it may be possible to do something like the solution on this question, but it seems overly complicated since the android:animateLayoutChanges option exists. I wonder if it's possible to solve my issue using that XML property, to keep it simple.

My animation code is as follows:

Java code

protected void expandCard() {
    if (isExpanded) {
        ibt_show_more.animate().rotation(0).start();
        isExpanded = false;
        tv_support.setVisibility(View.GONE);
    }
    else {
        ibt_show_more.animate().rotation(180).start();
        isExpanded = true;
        tv_support.setVisibility(View.VISIBLE);
    }
}

XML code

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/spacing_small"
    card_view:cardCornerRadius="2dp"
    android:id="@+id/os_list_item_cv">

    <RelativeLayout
        android:id="@+id/os_list_item_rl_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true">

        <!-- Here goes the header, the image, the action buttons and so on -->
        <!-- Omitted on purpose -->
        <!-- ... -->

        <!-- This is the support TextView -->
        <TextView
            android:id="@+id/tv_support"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/os_list_item_rl_actions"
            android:text="@string/bacon_ipsum"
            android:paddingBottom="24dp"
            android:paddingEnd="16dp"
            android:paddingRight="16dp"
            android:paddingLeft="16dp"
            android:paddingStart="16dp"
            android:visibility="gone"/>

    </RelativeLayout>

</android.support.v7.widget.CardView>

GIF for completeness (With wrong collapse behavior)

enter image description here

Mirage answered 1/2, 2017 at 15:4 Comment(6)
instead android:animateLayoutChanges you can use custom animation. ex. scalling support text from 0 to 1 for expand and for collaps scale from 1 to 0Headcloth
Care to write an example as an answer?Mirage
Can you post your animation code?Visionary
Posted the animation code.Mirage
please add the xml you are using for the layout animationAvuncular
does it work if you change the RL height to wrap_content?Avuncular
U
28

Right before you change the visibility, add this line of code:

TransitionManager.beginDelayedTransition(the rootView containing the cardView, new AutoTransition()); 

You should get a smooth animation. Also remove "animateLayoutChanges=true" from your xml before this.

As for why this works, calling TransitionManager.beginDelayedTransition() makes the TransitionManger capture current values in the parent ViewGroup and render the animations in the next animation frame. The Transition passed in this case is an AutoTransition, which takes care of all the fading, moving, and resizing in the parent ViewGroup.

See Transitions and TransitionManager

Also take care to use Transitions from the support library where appropriate, or perform the neccessary API level checks.

Unhealthy answered 1/2, 2017 at 16:17 Comment(3)
Thanks for adding the explanation. Please do make a habit of doing this in all answers you postSurefooted
I may add that it also works if I keep the animateLayoutChanges=true" if I put the TransitionManager only when I set the visibility to GONE.Mirage
note that the rootView provided to the function should be the parent of all views that should be affected by the animationAcis

© 2022 - 2024 — McMap. All rights reserved.