Ripple effect in pressed state + transparency in n

2019-04-12 06:24发布

问题:

I would like the ImageView in the ViewGroup, when pressed, draws the ripple and this is working! But when the ViewGroup is pressed, the ImageView inside it, should remain transparent otherwise the ImageView background is visible: (that color alpha-orange, you actually see, is the ripple when pressed).

This happens only with devices API 21+. With devices API <21 I use a selector and the image background remains transparent as wanted when the ViewGroup is pressed.

layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_detail_field"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="@dimen/margin_left"
    android:paddingStart="@dimen/margin_left"
    android:paddingTop="@dimen/margin_top_item_field"
    android:paddingBottom="@dimen/margin_bottom"
    android:baselineAligned="false"
    android:background="@drawable/layout"
    android:stateListAnimator="@anim/touch_raise"
    android:orientation="horizontal">

...

    <ImageView
        android:id="@+id/item_detail_showfield_icon"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/button_mini_oval"
        android:stateListAnimator="@anim/touch_raise"
        android:clickable="true"
        android:contentDescription="@null"
        android:scaleType="center"
        android:visibility="invisible"
        android:src="@drawable/show_button"/>

...

</LinearLayout>

drawable/button_mini_oval.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="oval">
            <solid android:color="@color/primary_highlight" />
        </shape>
    </item>
    <item>
        <shape android:shape="oval">
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
</selector>

drawable-v21/button_mini_oval.xml

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_shortAnimTime"
    android:color="?android:colorControlHighlight">

    <item android:state_pressed="true">
        <shape android:shape="oval">
            <solid android:color="@android:color/white" />
        </shape>
    </item>
    <item>
        <color android:color="@android:color/transparent" />
    </item>
</ripple>

I tried many configurations in the ripple xml, adding a <selector> it works (see below), but if you just tap the ImageView, the ripple is not visible (the ripple animation seems cut), only if you keep pressed you see the ripple...

What is the combination to have ripple in pressed state and transparent in normal state?

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_shortAnimTime"
    android:color="?android:colorControlHighlight">

    <item>
        <selector>
            <item android:state_pressed="true">
                <shape android:shape="oval">
                    <solid android:color="@android:color/white" />
                </shape>
            </item>
            <item>
                <color android:color="@android:color/transparent" />
            </item>
        </selector>
    </item>
</ripple>

回答1:

Removing android:state_pressed="true", I've found 2 solutions but in both cases I lost the touch_raise animation (why?):

With masked ripple:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_shortAnimTime"
    android:color="?android:colorControlHighlight">

    <item android:id="@android:id/mask">
        <selector>
            <item>
                <shape android:shape="oval">
                    <solid android:color="@android:color/white" />
                </shape>
            </item>
            <item>
                <color android:color="@android:color/transparent" />
            </item>
        </selector>
    </item>
</ripple>

With unmasked little ripple (nicer than 1):

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:exitFadeDuration="@android:integer/config_shortAnimTime"
    android:color="?android:colorControlHighlight">

    <selector>
        <item>
            <color android:color="@android:color/transparent" />
        </item>
    </selector>
</ripple>

I don't know why it is sufficient to add <selector> to have a ripple on a transparent background!!! a lot of people were trying to achieve this but it wasn't the intention of Google, instead it is very useful is such situations.



回答2:

With me, it works

<?xml version="1.0" encoding="utf-8"?>
    <ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/white"
    android:radius="3dp">
        <item android:drawable="@drawable/transparent_ripple_button"/>
</ripple>

and a separate

transparent_ripple_button.xml

in your folder

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/black_12" />
            <stroke android:width="0.2dp" android:color="@color/white" />
            <corners android:radius="3dp" />
        </shape>
    </item>

    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/black_12" />
            <stroke android:width="0.2dp" android:color="@color/white" />
            <corners android:radius="3dp" />
        </shape>
    </item>

    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/transparent" />
            <stroke android:width="0.2dp" android:color="@color/white" />
            <corners android:radius="3dp" />
        </shape>
    </item>

</selector>