Java – F.A.B hides but does not show

F.A.B hides but does not show… here is a solution to the problem.

F.A.B hides but does not show

Try implementing a float action button (F.A.B) that hides when scrolling down and appears when scrolling up.

I have ScrollAwareFABBehavior.java to manage it, which connects to F.A.B in XML activity_main. Question: F.A.B hides when I scroll down, but no longer shows when I scroll up. I documented the onNestedScroll method, which calls “Call Scroll” and “Call Hide” when scrolling down; But after hiding the F.A.B, there is no 3x Log

Question: Why doesn’t F.A.B. appear when scrolling up does not show F.A.B after it is 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>

Solution

Which support library version do you use in your project?

If you’re using the latest version (I mean 25.0.x), it’s because the fab.hide() method sets the visibility to View.GONE. This causes the nested scroll listener to stop checking the fab, which is the second time you try to scroll the list.

More details can be found here: https://code.google.com/p/android/issues/detail?id=230298

I searched a bit and found that this similar question already has a good answer:
Floating action button not visible on scrolling after updating Google Support & Design Library

THEREFORE, A POSSIBLE WORKAROUND IS TO OVERRIDE THE FAB.HIDE METHOD INSTEAD OF SETTING THE VISIBILITY TO GONE BUT TO INVISIBLE.

And I think this might be fixed later from upstream, so keep an eye on it.

Related Problems and Solutions