material-components-android icon indicating copy to clipboard operation
material-components-android copied to clipboard

[Button] Double ripple with icon buttons in 1.7.0-alpha03

Open OxygenCobalt opened this issue 2 years ago • 22 comments

Description: When I use my custom Icon Button style in 1.7.0-alpha03, a strange behavior occurs where two ripples appear. One ripple will appear where I touch (expected behavior), but another will appear in the center.

Here is a demonstration in the catalog (with the tonal button modified to use my style and without the icon to see the ripple clearer):

https://user-images.githubusercontent.com/65370175/179551670-4bf8769c-0611-4bcd-9cb0-438534dad11d.mp4

Here is a close-up of the two ripples to show that I'm not just seeing things:

image

This was seemingly introduced by the update to AppCompat 1.5.0-beta01 in e968929c08228f475f0f09c302da437a97180284. Re-compiling the project with AppCompat 1.4.0 solves the issue.

Expected behavior: Only one ripple should appear at the point where I pressed the button.

Source code: I use this style for my button

<style name="Widget.Auxio.Button.PlayPause" parent="Widget.Material3.Button.IconButton.Filled.Tonal">
    <item name="android:minWidth">72dp</item>
    <item name="android:minHeight">72dpitem>
    <item name="iconSize">32dpitem>
    <item name="android:insetTop">0dp</item>
    <item name="android:insetBottom">0dp</item>
    <item name="android:insetLeft">0dp</item>
    <item name="android:insetRight">0dp</item>
    <item name="android:paddingStart">12dp<item>
    <item name="android:paddingEnd">12dp<item>
    <item name="android:paddingTop">12dp<item>
    <item name="android:paddingBottom">12dp</item>
    <item name="shapeAppearanceOverlay">
        @style/ShapeAppearanceOverlay.Material3.FloatingActionButton
    </item>
</style>

Android API version: Any API version

Material Library version: 1.7.0-alpha03

Device: OnePlus 7T on Android 11. Probably also happens on Android 12+, but I can't completely tell due to the new ripple style.

OxygenCobalt avatar Jul 18 '22 15:07 OxygenCobalt

Any update on this? I'm unable to update several dependencies now, such as coil, as they are all bringing in the newer AppCompat versions and causing this issue.

OxygenCobalt avatar Aug 27 '22 21:08 OxygenCobalt

You mentioned that you are using a custom style. Does the issue occur without the custom style?

raajkumars avatar Aug 29 '22 14:08 raajkumars

Yes, it does @raajkumars. Even a MaterialButton with the default style will display this strange ripple behavior.

OxygenCobalt avatar Aug 29 '22 14:08 OxygenCobalt

@OxygenCobalt Thanks for confirming. From what you describe this appears to issue in the AppCompat framework. We will look into this and post an update.

raajkumars avatar Aug 29 '22 20:08 raajkumars

By the way at @raajkumars, this bug only occurs from appcompat 1.5.0-beta01 onwards. So I guess you could take a look at these commits so see where the issue was introduced. I can't really identify where it could have shown up, and I can't really bisect on my end to find the issue.

OxygenCobalt avatar Aug 30 '22 18:08 OxygenCobalt

Found this issue in the appcompat issue tracker. No updates though.

OxygenCobalt avatar Oct 14 '22 19:10 OxygenCobalt

Still shocked this hasn't been resolved, albeit I get it given that AppCompat isn't given too much attention. I'm going to try to debug this myself and make a PR for the AppCompat library.

OxygenCobalt avatar Dec 06 '22 23:12 OxygenCobalt

Okay, I am almost certain that the issue is caused by this diff in androidx commit f2936e8c0b6a4b73d214b31edf8cde566a879dcb or e8769968f3530f3dc40a547c373bcfb00ad72c13. It is the only code remotely related to Drawables in the 1.5.0-beta01 creation, and there the class this is in (ResourceManagerInternal) has direct connections to AppCompatButton and thus MaterialButton.

Here's the combined diff.

@@ -27,6 +27,7 @@ import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Drawable.ConstantState;
+import android.graphics.drawable.LayerDrawable;
 import android.os.Build;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -437,10 +438,22 @@ public final class ResourceManagerInternal {
     }
 
     static void tintDrawable(Drawable drawable, TintInfo tint, int[] state) {
-        if (DrawableUtils.canSafelyMutateDrawable(drawable)
-                && drawable.mutate() != drawable) {
-            Log.d(TAG, "Mutated drawable is not the same instance as the input.");
-            return;
+        int[] drawableState = drawable.getState();
+
+        boolean mutated = false;
+        if (DrawableUtils.canSafelyMutateDrawable(drawable)) {
+            mutated = drawable.mutate() == drawable;
+            if (!mutated) {
+                Log.d(TAG, "Mutated drawable is not the same instance as the input.");
+                return;
+            }
+        }
+
+        // Workaround for b/232275112 where LayerDrawable loses its state on mutate().
+        if (drawable instanceof LayerDrawable && drawable.isStateful()) {
+            // Clear state first, otherwise setState() is a no-op.
+            drawable.setState(new int[0]);
+            drawable.setState(drawableState);
         }
 
         if (tint.mHasTintList || tint.mHasTintMode) {

@raajkumars Can you please forward this to the androidx team? I've reported the issue here and have gotten no response whatsoever. I cannot report it the issue on the androidx github repository. My app has had to use obsoleted versions of appcompat, coil, and MDC for half a year now because of this visual error.

OxygenCobalt avatar Dec 30 '22 16:12 OxygenCobalt

@OxygenCobalt Thanks for the detailed root cause analysis.

raajkumars avatar Jan 19 '23 18:01 raajkumars

I can't reproduce it... (It doesn't seem that AppCompat has touched the code you pointed out though.)

Is this still reproducible if you update AppCompat version to 1.6.1?

drchen avatar Feb 09 '23 22:02 drchen

Hm. Were there any changes to MDC's ripple code between 1.7.0 and 1.8.0? I'm not able to test it right now since I am extremely busy, but I will get back to you as soon as possible. @drchen

OxygenCobalt avatar Feb 09 '23 22:02 OxygenCobalt

I can't recall anything regarding the button or ripple implementation change. (But we do update our AppCompat dependency version, not sure if it's related.)

drchen avatar Feb 10 '23 16:02 drchen

Very strange then. I remember trying AppCompat 1.7.0-alpha01 and seeing that the bug could still be re-produced. I'll go check again with different versions of MDC and AppCompat when I finally get time.

OxygenCobalt avatar Feb 10 '23 18:02 OxygenCobalt

Helpful

SiddiquiUbaid avatar Feb 11 '23 05:02 SiddiquiUbaid

I can still reproduce it @drchen. You can tell because when you press the button, the ripple color appears more "intense" initially, eventually it disappears leaving the (correct) less-intense ripple highlight color. That is the double ripple I am referencing, however due to how fast it is it's easy to misinterpret it as WAI. I've attached a video demonstration.

With the bug:

https://user-images.githubusercontent.com/65370175/218358071-043ef5b2-39b9-4f72-9b65-247781e72d70.mp4

Without the bug:

https://user-images.githubusercontent.com/65370175/218358097-0b9a1dd2-d552-4d86-bf98-cd2288ffcb83.mp4

OxygenCobalt avatar Feb 13 '23 02:02 OxygenCobalt

Another update: I've confirmed that MDC's RippleDrawableCompat is not related to the issue. If you are any RippleDrawable on any AppCompatButton, it will have a double ripple. Still trying to find the exact process where ResourceManagerInternal breaks the drawable.

OxygenCobalt avatar Feb 13 '23 15:02 OxygenCobalt

Hi @OxygenCobalt,

Is this still an issue related to Material? Any updates here?

hunterstich avatar Feb 23 '23 14:02 hunterstich

It is not an issue related to MDC @hunterstich. It's actually an issue where AppCompatButton mangles any RippleDrawable provided to it. Feel free to close this and forward people to the proper issuetracker entry.

OxygenCobalt avatar Feb 23 '23 14:02 OxygenCobalt

All material buttons are broken after the update and it's a pretty critical issue. Is there an ETA for when this will be fixed?

fsgjlp avatar May 04 '23 13:05 fsgjlp

@OxygenCobalt Thanks for the detailed analysis of the issue. Since the issue is caused by AppCompat, I expect that the fix for this issue will be made available in an upcoming AppCompat update.

raajkumars avatar May 04 '23 14:05 raajkumars

Reopening this to explore a possible fix suggested in https://issuetracker.google.com/262784311#comment5. See https://github.com/material-components/material-components-android/issues/3605#issuecomment-1737977097 for more background about this.

afohrman avatar Oct 02 '23 16:10 afohrman