15

I have an activity with coordinator layout.inside activity there is a fragment with Recycler view and float button.how can I show/hide float button when Scroll Recycler view and avoid to use fab behavior?!

in activity layout: CoordinatorLayout----->AppBarLayout---->Toolbar and FrameLayout and Bottom bar view

in fragment layout: RelativeLayout---->Recycler view and float button

I want to implement something like Google+ home page. how can I implement this scenario?


Temporary I used this solution for my problem:

using coordinator layout of activity by interface in my fragment and show/hide fab with fab behavior ... until I find better solution!!!

Community
  • 1
  • 1
Zahra.HY
  • 1,684
  • 1
  • 15
  • 25
  • 1
    You should probably implement some kind of scroll behavior for the FAB in your project then set layout_behavior property of the FAB to the custom scroll behavior you need. `app:layout_behavior="com.example.ScrollAwareFABBehavior"`... Tell me if you'd like a code snippet for this – KudzieChase Jan 17 '17 at 14:11
  • even fab doesn`t exist in coordinator layout? – Zahra.HY Jan 17 '17 at 14:13
  • I understand that you have a fragment layout with the FAB.. Well I advise you to move the FAB to the Activity Layout ... Carefully position it using `layout_gravity` e.g `start|bottom` since the coordinator layout is just a frame layout on steroids – KudzieChase Jan 17 '17 at 14:17
  • so my fab displays in all my fragments!! – Zahra.HY Jan 17 '17 at 14:18
  • In your current layout arrangement the FAB is within a FrameLayout not inside the Coordinator layout ... - You can show and hide it as you attach different fragments to the activity since it is a view – KudzieChase Jan 17 '17 at 14:19
  • yes it is and it doesn`t work well – Zahra.HY Jan 17 '17 at 14:20
  • Any better solution? i have similar problem, but instead of hide i want to move it down. – Anshul Kabra Sep 25 '20 at 11:39

5 Answers5

33

This code works just fine:

 mRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    if(dy > 0){
                        mFab.hide();
                    } else{
                        mFab.show();
                    }

                    super.onScrolled(recyclerView, dx, dy);
                }
            });

You cannot do:

app:layout_anchor="@id/listView"
app:layout_anchorGravity="bottom|end"

Look here:

There is no support built-in for CoordinatorLayout to work with ListView according to this Google post.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
Leandro Borges Ferreira
  • 12,422
  • 10
  • 53
  • 73
6

I modified Leondro's method such that the FAB will hide when there's scrolling and show when the scrolling stops.

scrollListener = new RecyclerView.OnScrollListener() {  
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        switch (newState) {
            case RecyclerView.SCROLL_STATE_IDLE:
                fab.show();
                break;
            default:
                fab.hide();
                break;
        }
        super.onScrollStateChanged(recyclerView, newState);
    }
}; 

rv.clearOnScrollListeners();
rv.addOnScrollListener(scrollListener);
Angel Koh
  • 12,479
  • 7
  • 64
  • 91
  • @behelit, it's not required. unless if you have other listeners already attached and want to remove them. – Angel Koh Feb 06 '19 at 11:06
5

You can add this property in your floating action button:

app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"

M_rey3000
  • 176
  • 3
  • 14
  • While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Dharman Dec 23 '20 at 16:25
1

Here is working solution:

class HideOnScrollFabBehavior(context: Context?, attrs: AttributeSet?) : FloatingActionButton.Behavior() {

    // changes visibility from GONE to INVISIBLE when fab is hidden because
    // due to CoordinatorLayout.onStartNestedScroll() implementation
    // child view's (here, fab) onStartNestedScroll won't be called anymore
    // because it's visibility is GONE
    private val listener = object : FloatingActionButton.OnVisibilityChangedListener() {
        override fun onHidden(fab: FloatingActionButton?) {
            fab?.visibility = INVISIBLE
        }
    }

    override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: FloatingActionButton, directTargetChild: View, target: View, axes: Int, type: Int): Boolean {
        return axes == ViewCompat.SCROLL_AXIS_VERTICAL // Ensure we react to vertical scrolling
                || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type)
    }

    override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: FloatingActionButton, target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, type: Int, consumed: IntArray) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed)
        if (!target.canScrollVertically(1) && dyConsumed > 0 && child.visibility == VISIBLE) {
            // hide the FAB when scroll view reached its bottom
            child.hide(listener)
        } else if (dyConsumed < 0 && child.visibility != VISIBLE) {
            // show the FAB on scroll up
            child.show()
        }
    }

}
a.yanyev
  • 31
  • 4
1

Solution in Kotlin

recycler_view = findViewById(R.id.recycler_view)

        recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener(){
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                if(dy > 0){
                    fab.hide();
                } else{
                    fab.show();
                }
                super.onScrolled(recyclerView, dx, dy)

            }
        })
Arsen Tagaev
  • 411
  • 7
  • 13