Ripples on a shape with a transparent background
Asked Answered
S

4

40

I am using the following shape in my app

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="oval" >
            <solid android:color="@color/primary_light"/>
            <size android:height="80dp" android:width="80dp"/>
        </shape>
    </item>

    <item android:state_focused="true">
        <shape android:shape="oval">
            <stroke android:color="@color/primary_light" android:width="5dp"/>
            <size android:height="80dp" android:width="80dp"/>
        </shape>
    </item>

    <item>
        <shape android:shape="oval">
            <solid android:color="@android:color/transparent"/>
            <size android:height="80dp" android:width="80dp"/>
        </shape>
    </item>
</selector>

It is there in my drawable folder. Now I am updating my app to Lollipop and I wish to give a ripple feedback on the circular button that I used. So in drawable-v21 folder I changed it to a ripple selector:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/primary_light">
    <item>
        <selector>
            <item android:state_focused="true">
                <shape android:shape="oval">
                    <stroke android:color="@color/primary_light" android:width="5dp"/>
                    <size android:height="80dp" android:width="80dp"/>
                </shape>
            </item>

            <item android:id="@android:id/mask">
                <shape android:shape="oval">
                    <solid android:color="@android:color/transparent"/>
                    <size android:height="80dp" android:width="80dp"/>
                </shape>
            </item>
        </selector>
    </item>
</ripple>

But unfortunately the ripple effect is not generated by using the above drawable in Lollipop. Is it because of the <solid android:color="@android:color/transparent"/>?

Can anyone show me where I have go wrong? Thanks

Soniasonic answered 4/4, 2015 at 10:30 Comment(1)
Had the same problem with <solid android:color="@android:color/transparent"/> used as a mask in a ripple. It doesn't seem to take into account the inner item shape if it is transparent. \n Your solution uses @android:color/white instead of transparent and that's what gets it to work actually, I think.Moseley
S
70

After a few trial and errors it seems I have misunderstood the hierarchy of the selector and item.

The following works perfectly.

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/primary_light">
        <item android:id="@android:id/mask">
               <shape android:shape="oval">
                       <solid android:color="@android:color/white"/>
                       <size android:height="80dp" android:width="80dp"/>
               </shape>
        </item>
</ripple>
Soniasonic answered 14/4, 2015 at 15:33 Comment(3)
This is not with a transparent background.. Did you manage to set ripple with a transparent background as well?Topology
@anoniim It works for transparent background #30216163Perimeter
From what I understand, the ripple effect can only be applied on color. So a complete transparent background will never show ripple effect. We should change background to some faded color (if not opaque) on press.Scrod
C
62

This works with a transparent background:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorControlHighlight"
    android:exitFadeDuration="@android:integer/config_shortAnimTime">
<!-- Use this to define the shape of the ripple effect (rectangle, oval, ring or line). The color specified here isn't used anyway -->
<item android:id="@android:id/mask">
    <shape android:shape="rectangle">
        <corners android:radius="3dp"/>
        <!-- This color is needed to be set - doesn't affect anything -->
        <solid android:color="@android:color/white"/>
    </shape>
</item>
<!-- This is the background for your button -->
<item>
    <!-- Use the shape you want here -->
    <shape android:shape="rectangle">
        <!-- Use the solid tag to define the background color you want -->
        <solid android:color="@android:color/transparent"/>
    </shape>
</item>
</ripple>

This was modified a bit from this answer: Transparent ripple

Cacilia answered 12/12, 2016 at 8:44 Comment(4)
This is what i am looking. Thanks for this answerPhthisic
Works like a charmCalendra
Thank you, it really works! White color as background for <item android:id="@android:id/mask"> really doesn't affect anything.Brittani
If you want to have a ripple on a transparent shape, this is the way to do it. Thanks God I've found this. I've already wasted 1 hour.Charette
H
7

Following code works for custom shape with ripple effect for transparent button -

main_activity_buttons_ripple_with_background.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#888888"
    tools:targetApi="lollipop">

    <!-- Use this to define the shape of the ripple effect (rectangle, oval, ring or line). The color specified here isn't used anyway -->
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <corners android:radius="25dp" />
            <!-- This color is needed to be set - doesn't affect anything -->
            <solid android:color="#000" />
        </shape>
    </item>

    <!-- This is the background for your button -->
    <item>
        <!-- Use the shape you want here -->
        <shape android:shape="rectangle">
            <!-- Use the solid tag to define the background color you want -->
            <solid android:color="@android:color/transparent" />
            <stroke
                android:width="1dp"
                android:color="#FFF" />
            <corners android:radius="25dp" />
        </shape>
    </item>

</ripple>

styles.xml

<style name="MainActivityButtonsStyle">
    <item name="android:background">@drawable/main_activity_buttons_ripple_with_background</item>
    <item name="android:textAllCaps">false</item>
    <item name="android:layout_margin">15dp</item>
    <item name="android:paddingLeft">20dp</item>
    <item name="android:paddingRight">20dp</item>
    <item name="android:layout_centerHorizontal">true</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">50dp</item>
    <item name="android:textColor">#FFF</item>
    <item name="android:textSize">18sp</item>
</style>

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">

        <Button
            android:layout_alignParentTop="true"
            style="@style/MainActivityButtonsStyle"
            android:text="@string/button_search_by_id" />
    
    </RelativeLayout>
    
</LinearLayout>
Honeysucker answered 12/9, 2017 at 16:19 Comment(0)
T
7

You can have a ripple effect on transparent or semi-transparent background when the ripple mask is specified. The ripple mask is a Drawable but only the alpha value is used setting the ripple alpha per pixel. Here is an example for creating programmatically.

var background = new android.graphics.drawable.GradientDrawable();
background.setShape(android.graphics.drawable.GradientDrawable.RECTANGLE);
background.setColor(0x77FFFFFF); // semi-transparent background
background.setCornerRadius(10);
background.setStroke(3, 0xFF1144FF); // border color

var mask = new android.graphics.drawable.GradientDrawable();
mask.setShape(android.graphics.drawable.GradientDrawable.RECTANGLE);
mask.setColor(0xFF000000); // the color is irrelevant here, only the alpha
mask.setCornerRadius(5); // you probably want the same corner as the background

var rippleColorLst = android.content.res.ColorStateList.valueOf(
    android.graphics.Color.argb(255,50,150,255)
);

// aaaand
var ripple = new android.graphics.drawable.RippleDrawable(rippleColorLst,background,mask);
yourButton.setBackground(ripple);

(Sorry for the JavaScript/NativeScript code, probably one can understand it)

Trope answered 25/6, 2018 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.