Trying to implement a Floating Action Button
(F.A.B) that hides on scroll down, and shows on scroll up.
I have ScrollAwareFABBehavior.java
to manage this, and it's connected to the F.A.B in in the XML activity_main
. Problem: The F.A.B hides on scroll down, but doesn't show again when I scroll up. I logged the onNestedScroll
method and it calls "calling scroll" and "calling to hide" while scrolling down; but after the F.A.B is hidden there are none of the 3x Log
's
Question: Why does the F.A.B not show when I scroll up, after the F.A.B has been hidden.
ScrollAwareFABBehavior.java:
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super();
}
@Override
public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
final View directTargetChild, final View target, final int nestedScrollAxes) {
// Ensure we react to vertical scrolling
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
|| super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public void onNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
final View target, final int dxConsumed, final int dyConsumed,
final int dxUnconsumed, final int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
Log.d("test", "calling scroll");
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
// User scrolled down and the FAB is currently visible -> hide the FAB
Log.d("test", "calling to hide");
child.hide();
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
// User scrolled up and the FAB is currently not visible -> show the FAB
Log.d("test", "calling to show");
child.show();
}
}
}
activity_main.xml:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="companyname.appname.MainActivity">
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rv_contactlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="16dp"
android:paddingTop="16dp"
android:scrollbars="vertical" />
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:src="@drawable/ic_add_circle_outline_black_24dp"
app:layout_anchor="@id/rv_contactlist"
app:layout_anchorGravity="bottom|right|end"
android:layout_alignParentEnd="true"
app:fabSize="normal"
android:layout_alignParentBottom="true"
android:onClick="addItem"
app:layout_behavior="companyname.appname.ScrollAwareFABBehavior"/>
</android.support.design.widget.CoordinatorLayout>
Which support library version are you using in your project?
If you are using the latest one ( I mean 25.0.x), this is because fab.hide() method set the visibility to be View.GONE. This makes nested scroll listener stop to check fab, the second time you try to scroll the list.
More detail can be found here: https://code.google.com/p/android/issues/detail?id=230298
And I search a bit found this similar question already have a nice answer: Floating action button not visible on scrolling after updating Google Support & Design Library
So a possible work around would be to override fab.hide method, not to set the visibility to GONE but INVISIBLE instead.
And I think this may be fixed from upstream later, so just keep an eye on it.
Because the update of Android to 25.0.x+ you should set the fab button with the listener to INVISBLE to show again the fab button, my solution is the next:
public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
private static final String TAG = "ScrollAwareFABBehavior";
public ScrollAwareFABBehavior(Context context, AttributeSet attrs) {
super();
}
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull FloatingActionButton child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) {
return true;
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
if(dependency instanceof RecyclerView)
return true;
return false;
}
@Override
public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull FloatingActionButton child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
child.hide(new FloatingActionButton.OnVisibilityChangedListener() {
@Override
public void onHidden(FloatingActionButton fab) {
super.onHidden(fab);
fab.setVisibility(View.INVISIBLE);
}
}
);
} else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
child.show();
}
}
}
** Tested in a Nexus 6P with Android Oreo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With