0

I am displaying a go to top button on scroll up on a RecyclerView. If user scrolls up the button is displayed.

Here is the xml code which is nested in a RelativeLayout.

<android.support.v7.widget.RecyclerView
    android:id="@+id/userFeedsRecyclerView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

<Button
    android:id="@+id/btn_goto_top"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:text="@string/icon_up_arrow"
    android:layout_alignParentBottom="true"
    android:layout_marginBottom="20dp"
    android:visibility="gone"
    android:textSize="10sp"
    android:layout_centerHorizontal="true"
    android:background="@drawable/round_button"/>

Here is the java code

btnGotoTop = (Button) findViewById(R.id.btn_goto_top);
    Const.setTypeFace(btnGotoTop, getApplication());
    btnGotoTop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            userFeedsRecyclerView.smoothScrollToPosition(0);
            view.setVisibility(View.GONE);
        }
    });


    userFeedsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            if(dy < 0){
                btnGotoTop.setVisibility(View.VISIBLE);
            }
            else{
                btnGotoTop.setVisibility(View.GONE);
            }
        }
    });

Inside the onClick() method of btnGotoTop, the RecyclerView scrolls to the top properly but the button does not disappear. I tried changing view.setVisibility(View.GONE) to btnGotoTop.setVisibility(View.GONE) but the button is displayed even after scrolling is complete.

Edric
  • 24,639
  • 13
  • 81
  • 91
Chandan Pednekar
  • 525
  • 5
  • 19

4 Answers4

0

Your condition is wrong. You are making button visible on scrolling but you want to show only when its down. change this

if(dy < 0){
            btnGotoTop.setVisibility(View.VISIBLE);
        }
        else{
            btnGotoTop.setVisibility(View.GONE);
        }

to

if(dy > 0){
            btnGotoTop.setVisibility(View.VISIBLE);
        }
        else{
            btnGotoTop.setVisibility(View.GONE);
        }
Amrish Kakadiya
  • 974
  • 1
  • 7
  • 25
0

Try this, I also recommend you to use floating action button here. I created a simple project in case you wanna have a look for recylerView with FloatingActionButton with same functionality required. Link.

    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
           if (dy > 0 && btnGotoTop.getVisibility() == View.VISIBLE) 
           {
                    btnGotoTop.hide();

           } else if (dy < 0 && btnGotoTop.getVisibility() != View.VISIBLE) 
           {
                    btnGotoTop.show();
           }

    }
});
Prashant Abdare
  • 2,175
  • 14
  • 24
  • the logic of showing and hiding the button on scroll works fine. What doesn't work is hiding the button when the scrolltoposition is complete. I was pointing at the onClick() method for the button. – Chandan Pednekar Apr 02 '18 at 12:30
0
 private boolean IsRecyclerViewAtTop(){
    if (userFeedsRecyclerView.getChildCount() == 0)
        return true;
    return userFeedsRecyclerView.getChildAt(0).getTop() == 0;
}


userFeedsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (IsRecyclerViewAtTop())
                {
                    btnGotoTop.setVisibility(View.GONE);
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (dy < 0 && btnGotoTop.getVisibility()==View.GONE) {
                    btnGotoTop.setVisibility(View.VISIBLE);
                } else if (dy > 0 && btnGotoTop.getVisibility()==View.VISIBLE){

                    btnGotoTop.setVisibility(View.GONE);
                }
            }
        });

Use IsRecyclerViewAtTop method to find out if recycler view scrolled to top and call it is onScrollStateChanged method.

Suraj Vaishnav
  • 7,777
  • 4
  • 43
  • 46
0

Here is how I solved it. Changed visibility of button in onScrollStateChanged() of RecyclerView's OnScrollListener

btnGotoTop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View view) {
            userFeedsRecyclerView.smoothScrollToPosition(0);
            view.setVisibility(View.GONE);
            headerAppBarLayout.setExpanded(true);
        }
    });

private boolean isUserFeedRecyclerViewAtTop(){

    int numColumns = 2;
    int pos[] = new int[numColumns];
    ((StaggeredGridLayoutManager)(userFeedsRecyclerView.getLayoutManager())).findFirstCompletelyVisibleItemPositions(pos);
    return pos[0] == 0;
}

userFeedsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            switch (newState){
                case RecyclerView.SCROLL_STATE_IDLE:
                    if(isUserFeedRecyclerViewAtTop()) {
                        btnGotoTop.setVisibility(View.GONE);
                    }
                    break;
                case RecyclerView.SCROLL_STATE_DRAGGING:
                    break;
                case RecyclerView.SCROLL_STATE_SETTLING:
                    break;
            }
        }

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

            if(dy < 0 && btnGotoTop.getVisibility() == View.GONE){
                btnGotoTop.setVisibility(View.VISIBLE);
            }
            else if (dy > 0 && btnGotoTop.getVisibility() == View.VISIBLE){
                btnGotoTop.setVisibility(View.GONE);
            }
        }
    });
Chandan Pednekar
  • 525
  • 5
  • 19