Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Floating Action Buttons disappearing on scroll

I've just installed the FutureSimple library for Floating Action Buttons, and I think it's just beautiful. Although it doesn't contain the disappear on scroll logic, I love it. However, I would like to implement a Quick Return pattern and I'm looking for a simple way to do it. Basically, I set up an ObservableListView listener like so :

    listView.setScrollViewCallbacks(new ObservableScrollViewCallbacks() {
        @Override
        public void onScrollChanged(int i, boolean b, boolean b2) { }

        @Override
        public void onDownMotionEvent() { }

        @Override
        public void onUpOrCancelMotionEvent(ScrollState scrollState) { }
    });

And I want to know if there's a simple way to make my button move (with a quick button.animate().translationY(xx)) with this listener.

So that whenever I scroll down, it disappears, and then it reappears when I scroll up.

I've looked at differents implementations, but I haven't quite understood the jist of them (especially the "official" fab library from makovkastar).

PS : I'm using the FutureSimple library because it has menus.

Thank you very much, in advance, for your much wanted help :) !

like image 693
Mehdi Avatar asked Feb 28 '15 16:02

Mehdi


People also ask

Is Floating Action button docked?

You can dock a FloatingActionButton by specifying floatingActionButtonLocation in a Scaffold and using BottomAppBar .


1 Answers

I solved my problem a few weeks ago, and I figured I should probably answer my own question here :)

After several days of research, I had found that the best way to implement this is by using the new RecyclerView introduced by Android. You can handle small pixel changes in scrolling with RecyclerView, but with ListView you would almost never be able to do that (only can handle change of "items" scrolled). I've implemented a ScrollView Listener to my RecyclerView like this :

   public abstract class HidingScrollListener extends RecyclerView.OnScrollListener {
private static final int HIDE_THRESHOLD = 20;
private int scrolledDistance = 0;
private boolean controlsVisible = true;

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);

    int firstVisibleItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
    //show views if first item is first visible position and views are hidden
    if (firstVisibleItem == 0) {
        if(!controlsVisible) {
            onShow();
            controlsVisible = true;
        }
    } else {
        if (scrolledDistance > HIDE_THRESHOLD && controlsVisible) {
            onHide();
            controlsVisible = false;
            scrolledDistance = 0;
        } else if (scrolledDistance < -HIDE_THRESHOLD && !controlsVisible) {
            onShow();
            controlsVisible = true;
            scrolledDistance = 0;
        }
    }

    if((controlsVisible && dy>0) || (!controlsVisible && dy<0)) {
        scrolledDistance += dy;
    }
}

public abstract void onHide();
public abstract void onShow();

This code does MORE than just show or hide FABs on scroll, it actually handles a pretty perfect "action bar disappears on scrolling" effect. But, I don't have time to suit this code to your needs, but it does work for our case, here.

To get back to our code, after creating our listener, we can add it to our FABs by implementing its interfaces :

           recyclerView.setOnScrollListener(new HidingScrollListener() {
        @Override
        public void onHide() {
                    FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) fam.getLayoutParams();
    int fabBottomMargin = lp.bottomMargin;
    fam.animate().translationY(fam.getHeight()+fabBottomMargin).setInterpolator(new AccelerateInterpolator(2)).start();
        }

        @Override
        public void onShow() {
                    toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
    fam.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2)).start();
        }
    });

And Voilà !

like image 85
Mehdi Avatar answered Sep 18 '22 15:09

Mehdi