Material ripple effect hidden by other view in layout
Asked Answered
P

6

20

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?

Photostat answered 11/8, 2015 at 17:25 Comment(2)
could you check my answer below and determine if it is acceptable or not? https://mcmap.net/q/609136/-material-ripple-effect-hidden-by-other-view-in-layout Thank youInconsiderable
Hi Santiago, sorry I didn't check your answer as I've been working on another project since then and kinda forgot about this question. I'll give it a try and get back to you as soon as I can.Photostat
I
70

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.

Inconsiderable answered 10/6, 2016 at 21:6 Comment(6)
This does the job, thanks! On a side note I'd replace the root RelativeLayout with a FrameLayout as we're just displaying the child views as isPhotostat
@Jukurrpa, that's right, we should avoid RelativeLayout because it is more inefficient. Using FrameLayout would be betterInconsiderable
This resulted in a clipped ripple in my case (overflow button at top right-hand side of container). Should anyone else run into the same issue, using padding instead of margin resolved the clipped ripple.Prompt
so many questions and answers of the same problem, but this one got solved this issue.Foran
Set the bounding FrameLayout larger than (about twice) the ImageView not to cut borderless ripple.Diesis
In addition to the parent's background I also had to set some padding on my ImageButton.Manzo
A
11

I'm aware this is an old post but I did struggle with this quite a bit today hence I'm posting what I was finally able to figure out and maybe someone else might benefit from it. One key emphasis beforehand, please do always RTFM!

1) The story

I aimed to use the unbounded ripple effect on Tab Items and consequently have it spread all over the AppBarLayout area. I had applied @android:color/transparent to TabLayout as the first wrapping parent and gave AppBarLayout a background color, nevertheless the ripple was still being cut off right at the borders of TabLayout's height.

2) The moral of the story (RTFM)

So I run to the nest of Android knowledge: The Documentation, and spotted this:

?android:attr/selectableItemBackgroundBorderless for a ripple that extends beyond the view. It will be drawn upon, and bounded by, the nearest parent of the view with a non-null background.

3) The course of action

Using Layout Inspector, I realized that @android:color/transparent although transparent (duh!) it actually assigns 0 as the value of the bg attribute of a View, but zero is not null hence the ripple gets bounded at the nearest parent.

4) The conclusion

With that in hand, I went and set the android:background property of my TabLayout to @null rather than transparent, and now I have a fancy little ripple spread onto the area of the AppBarLayout.

5) Outro: **ANDROID & SO FTW!

Props to everyone in this post who shed light on the matter in word. Cheers!

Asset answered 28/7, 2017 at 16:41 Comment(0)
B
9

I am experiencing same issue. Only solution I have found so far is not 100% okay since ripple is masked by view (its not borderless).

The solution (workaround): surround your ImageButton with other view and set ripple to the foreground instead of the background in your layout like this:

<ImageView ... /> 

<FrameLayout
    ...
    android:clickable="true"
    android:focusable="true"
    android:foreground="?attr/selectableItemBackgroundBorderless" >

    <ImageButton />
</FrameLayout>

I would be really glad if someone explain why the ripple is drawn behind the image. Also if you look at Google Photos app, in image detail they have transparent icons over image view with ripple. I would like to replicate this, but I am not able to make the ripple to be in foreground. Does anybody know how to put transparent imagebuttons over everything but still have the ripple?

EDIT final solution here you can find exactly same question link

with great explanation what is happening. the solution is the same but on top of that it solves rectangular mask by adding

android:clipChildren="false"
android:clipToPadding="false"

to your layout. now your ripple should be borderless (it worked for me). The layout xml could be something like this:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:clipChildren="false"
android:clipToPadding="false">

    <ImageView ... /> 

    <FrameLayout
        ...

        android:clickable="true"
        android:foreground="?attr/selectableItemBackgroundBorderless">
       <ImageView ... />
    </FrameLayout>

</FrameLayout>
Barbital answered 13/3, 2016 at 17:0 Comment(1)
Thank you! It solved my issue. Just had to add those two lines to the parent and it worked!Malaguena
D
1

After wrapping ImageButton inside FrameLayout, I was getting rectangular shape on touch. Applied background with oval shape on FrameLayout and got the circular shape on touch.

Dual answered 12/5, 2019 at 15:22 Comment(0)
P
1

Had the same issue. Used the solutions described above and worked. Managed to avoid the wrapping FrameLayout by setting foreground as ?attr/actionBarItemBackground and background as @null.

 <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center|end"
            android:background="@null"
            android:contentDescription="@string/app_name"
            android:foreground="?attr/actionBarItemBackground"
            android:padding="@dimen/small_margin"
            android:src="@drawable/ic_clear_text_icon" />
Pneumodynamics answered 23/2, 2021 at 7:57 Comment(0)
A
1

Use android:clipChildern="false" android:clipToPadding="false" for ALL the parent layouts

here is my solution.

` <LinearLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:clipToPadding="false" >

    <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:clipChildren="false"
      android:clipToPadding="false">

      <ImageButton
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:foreground="?attr/selectableItemBackgroundBorderless"
        android:src="@drawable/ic_magnifier" />

         ....
        `
Anguine answered 27/2, 2023 at 11:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.