Search code examples
androidandroid-layoutmaterial-designrippledrawable

Material ripple effect hidden by other view in layout


I added a ripple effect on a ImageButton, however it is hidden by an ImageView used as a background for the parent view RelativeLayout.

Here's the layout file:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="172dp"
                android:orientation="vertical"
                android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/drawerBackgroundImageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/drawer_background"/>

    [...]

    <ImageButton
        android:id="@+id/drawerLogoutButton"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:layout_alignBottom="@id/drawerEmailTextView"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:layout_marginEnd="@dimen/activity_horizontal_margin"
        android:layout_marginRight="@dimen/activity_horizontal_margin"
        style="@style/FlatButtonStyle"
        android:scaleType="centerInside"
        android:src="@drawable/ic_logout_white_24dp"/>

</RelativeLayout>

(there's a bunch of other views but they're irrelevant here)

I'm using an ImageView as the background for the RelativeLayout as I need to set a specific scaleType for the image, so I can't use the basic android:background property.

The ripple effect is hidden as it doesn't have a mask layer (I want it to extend out of the button's bounds) and thus uses the ImageButton's parent view to be displayed. The effect is perfectly visible if I remove the ImageView.

Is there a way to get the ripple effect to be shown above the problematic ImageView?


Solution

  • I had exactly the same issue and solved it using this thread: https://code.google.com/p/android/issues/detail?id=155880

    Issue preview:

    Before solved:

    Before

    After solved:

    After

    Explanation:

    "Borderless buttons draw their content on the closest background. Your button might not be having background between itself and the ImageView, so it draws underneath the ImageView."

    Solution:

    "Use a transparent background (android:background="@android:color/transparent") on some layout containing the button (beneath the ImageView). This will dictate what the maximum bounds of the ripple effect is."

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
                    ...>
    
        <!-- Your background ImageView -->
        <ImageView
            android:id="@+id/drawerBackgroundImageView"
            android:src="@drawable/drawer_background"
            ... />
    
            <!-- ... -->
    
        <!-- HERE, you need a container for the button with the transparent
             background. Let's say you'll use a FrameLayout -->
        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/transparent">
    
            <!-- Maybe more items --> 
    
            <!-- Button with borderless ripple effect -->
            <ImageButton
                android:id="@+id/drawerLogoutButton"
                android:background="?selectableItemBackgroundBorderless"
                ... />
    
        </FrameLayout>
    
    </FrameLayout>
    

    Hope it helps.