2

On all of my layouts, my FloatingActionButtons' ripple effects are persisting if the user lifts their finger outside of the FAB view. i.e. User presses down on white FAB, ripple happens turning FAB gray, user drags finger away from button and lifts it, and the button stays gray.

Here is a sample fab XML:

<android.support.design.widget.FloatingActionButton
            android:id="@+id/fab_pinfav"
            android:layout_width="@dimen/fab_size"
            android:layout_height="@dimen/fab_size"
            android:src="@drawable/icon_unfavd"
            app:elevation="8dp"
            android:elevation="8dp"
            android:layout_gravity="bottom|end"
            android:layout_marginRight="@dimen/spacingMedium"
            android:layout_marginEnd="@dimen/spacingMedium"/>

And all FABs are direct children of varying basic CoordinatorLayouts, i.e.

<android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

Tested on various devices ranging from Android 5.1 to Android 7.1, with the same issue on each.

I have not seen any similar occurrences on my other views as they respond to touch effects.

EDIT: Related Google Issue https://code.google.com/p/android/issues/detail?id=218956 (see 'Issue #2') The issue is present in Design Library v25.0.0 and not present in v23.4.0

FINAL EDIT: This bug was fixed with the Support library 25.1.0 release https://developer.android.com/topic/libraries/support-library/revisions.html# If you are encountering this issue, update your support library version to 25.1.0.

Demonsoul
  • 791
  • 4
  • 11

1 Answers1

5

I believe this is due to a fix merged to correct FloatingActionButton's clickable area in pre-Lollipop versions. This fix overrides the onTouchEvent() method to return false if the touch occurs outside of the content area. Unfortunately, this has the effect of stopping any further touch events being delivered to the View, so it never receives the ACTION_UP, and therefore does not update its pressed state accordingly.

We should be able to fix this fix by subclassing FloatingActionButton, overriding onTouchEvent() ourselves, checking the return from the super call, and setting the pressed state correctly if the event has left the content area.

public class CustomFAB extends FloatingActionButton {

    public CustomFAB(Context c, AttributeSet a) {
        super(c, a);
    }

    // Additional constructors as needed
    // ...

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean result = super.onTouchEvent(ev);
        if (!result) {
            setPressed(false);
        }
        return result;
    }
}
Mike M.
  • 38,532
  • 8
  • 99
  • 95
  • This worked, thank you. So the bug is in the support library and not my code; will your solution raise any issues with pre-lollipop support? Also, would it be a better interim solution to just revert to using an older support library version? Cheers. – Demonsoul Nov 03 '16 at 15:30
  • 1
    I was just running a quick test on what I have available right this minute, which is my KitKat device, and it works as expected on that version. I don't foresee any major problems with other versions, though, of course, I've not tested everywhere. You certainly could revert to an older library version, but I'm not sure exactly what the "clickable area" problem was, as the merge comment is vague, so it may actually be less desirable behavior. I'm also unsure of how long that interim might be, as it looks like they've not yet addressed the issue in even the most recent source I can find. Cheers! – Mike M. Nov 03 '16 at 15:40
  • 1
    I dug up the related Issue buried in Google's Issue Tracker here: https://code.google.com/p/android/issues/detail?id=218956 Someone reports the issue as introduced in v23.4.0, so rather than go back I will use this CustomFAB solution. I believe your solution is better than what people have suggested there as well, if you'd like to spread it around. Thanks! – Demonsoul Nov 03 '16 at 15:43
  • 1
    Ah, good find. I think it was actually introduced a little later than 23.4.0, as that's the version I tested on, and the behavior wasn't present. I had to simulate it by first creating another subclass to insert it. The very last entry there is close to my answer, but I think the long click handling is unnecessary. It did make me realize, though, that doing the content area check again is redundant. We can just use the return from the super call. Duh. I'll update my answer, and do a little more testing to make sure I'm correct about the long click. Glad it worked for ya. Cheers! – Mike M. Nov 03 '16 at 16:00
  • 1
    Wonderful, thanks again! May want to get rid of the Rect initializer now as well. Actually I misread earlier, the comment said it **didn't** happen in v23.4.0 – Demonsoul Nov 03 '16 at 16:08
  • Oop, yep, nice catch. Thanks! – Mike M. Nov 03 '16 at 16:18