Search code examples
androidandroid-elevation

Why does the click effect disappear when using the stateListAnimator property?


enter image description here

I made a button with the desired design as shown in the picture.

But when I click the button, the click effect does not appear.

The cause lies in the stateListAnimator="@null" property.

Clearing this property has no elevation effect.

And also, if you don't apply the backgroundTint to white, the shaodw is not visible.

This is a must have property because I want an elevation effect on a button.

The second way I do it is to use OutLineButton.

This also creates a similar design i want, but applying only 1dp of elevation effect will apply excessive elevation effect.

I don't know why either.

What should I do?

Why is this happening?

<Button
    android:id="@+id/delete_set"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:backgroundTint="@color/white"
    android:drawableLeft="@drawable/ic_remove_routine"
    android:text="DELETE SET"
    android:textSize="12dp"
    android:textColor="@color/orgin_text_color"
    android:elevation="10dp"
    android:stateListAnimator="@null"
    android:layout_marginTop="10dp"
    android:layout_marginLeft="1dp"
    android:layout_marginRight="1dp"
/>
<Button
    android:id="@+id/add_set"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:drawableLeft="@drawable/ic_add_routine"
    android:backgroundTint="@color/white"
    android:text="ADD SET"
    android:textSize="12dp"
    android:textColor="@color/orgin_text_color"
    android:elevation="10dp"
    android:stateListAnimator="@null"
    android:layout_marginTop="10dp"
    android:layout_marginLeft="1dp"
    android:layout_marginRight="1dp"
 />

Solution

  • Actually, you're removing the default StateListAnimator, as the name suggests you're nulling the property responsible for animating the button based on the state, so the button is behaving as expected. Note that the elevation property in StateListAnimator override the property on the button itself.

    To achieve what you want, instead of setting StateListAnimator to null, you should implement your custom one. For reference, you can view the default animator here.

    To do so, you can define a dimen in dimens.xml like this:

    <dimen name="my_button_elevation">10dp</dimen>
    

    Then, create an xml resource in animator/ folder called for example my_button_animator.xml with the following content:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="true" android:state_enabled="true">
            <set>
                <objectAnimator android:propertyName="translationZ"
                                android:duration="100"
                                android:valueTo="4dp"
                                android:valueType="floatType"/>
                <objectAnimator android:propertyName="elevation"
                                android:duration="0"
                                android:valueTo="@dimen/my_button_elevation"
                                android:valueType="floatType"/>
            </set>
        </item>
        <!-- base state -->
        <item android:state_enabled="true">
            <set>
                <objectAnimator android:propertyName="translationZ"
                                android:duration="100"
                                android:valueTo="0"
                                android:startDelay="100"
                                android:valueType="floatType"/>
                <objectAnimator android:propertyName="elevation"
                                android:duration="0"
                                android:valueTo="@dimen/my_button_elevation"
                                android:valueType="floatType" />
            </set>
        </item>
        <item>
            <set>
                <objectAnimator android:propertyName="translationZ"
                                android:duration="0"
                                android:valueTo="0"
                                android:valueType="floatType"/>
                <objectAnimator android:propertyName="elevation"
                                android:duration="0"
                                android:valueTo="0"
                                android:valueType="floatType"/>
            </set>
        </item>
    </selector>
    

    Finally, you can use the property as follows

    <item name="android:stateListAnimator">@animator/my_button_animator</item>
    

    And delete the elevation property from the buttons as it will be overriden by the animator.