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.
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;
}
}