Hiding ActionBar in RecyclerView / ListView onScroll

In my application, I got activity with some kind of action bar at the top and a list below. What I want to do is scroll it up with the list so that it is hiding, and then when the list scrolls down, it should scroll down with the list, as if it were just above the top of the screen. How can I achieve this functionality?

+46
android android-listview scroll android-actionbar vertical-scrolling
Nov 26 '12 at 5:45
source share
7 answers

Updated 6/3/2015:

Google now supports this with CoordinatorLayout .

 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_content" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:layout_scrollFlags="scroll|enterAlways" /> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.AppBarLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="@dimen/fab_margin" android:src="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout> 

Source: https://github.com/chrisbanes/cheesesquare/blob/master/app/src/main/res/layout/include_list_viewpager.xml

Documented here: https://developer.android.com/reference/android/support/design/widget/AppBarLayout.html

Original answer:

An example similar to the Google Play Music and Umano applications:

https://github.com/umano/AndroidSlidingUpPanel

Take a look at the code in this repository. When you slide the panel up, the ActionBar also slides.

From the demo :

  getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY); SlidingUpPanelLayout layout = (SlidingUpPanelLayout) findViewById(R.id.sliding_layout); layout.setShadowDrawable(getResources().getDrawable(R.drawable.above_shadow)); layout.setAnchorPoint(0.3f); layout.setPanelSlideListener(new PanelSlideListener() { @Override public void onPanelSlide(View panel, float slideOffset) { Log.i(TAG, "onPanelSlide, offset " + slideOffset); if (slideOffset < 0.2) { if (getActionBar().isShowing()) { getActionBar().hide(); } } else { if (!getActionBar().isShowing()) { getActionBar().show(); } } } @Override public void onPanelExpanded(View panel) { Log.i(TAG, "onPanelExpanded"); } @Override public void onPanelCollapsed(View panel) { Log.i(TAG, "onPanelCollapsed"); } @Override public void onPanelAnchored(View panel) { Log.i(TAG, "onPanelAnchored"); } }); 

Download the example here:

https://play.google.com/store/apps/details?id=com.sothree.umano

enter image description here

ListView - without libraries:

I recently needed the same functionality, and this works fine for me:

As the user scrolls up, the ActionBar will be hidden to give the user the ability to work full screen.

When the user scrolls down and releases, the ActionBar will return.

 getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY); listView.setOnScrollListener(new OnScrollListener() { int mLastFirstVisibleItem = 0; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view.getId() == listView.getId()) { final int currentFirstVisibleItem = listView.getFirstVisiblePosition(); if (currentFirstVisibleItem > mLastFirstVisibleItem) { // getSherlockActivity().getSupportActionBar().hide(); getSupportActionBar().hide(); } else if (currentFirstVisibleItem < mLastFirstVisibleItem) { // getSherlockActivity().getSupportActionBar().show(); getSupportActionBar().show(); } mLastFirstVisibleItem = currentFirstVisibleItem; } } }); 

RecyclerView - no libraries

  this.mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { int mLastFirstVisibleItem = 0; @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); final int currentFirstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition(); if (currentFirstVisibleItem > this.mLastFirstVisibleItem) { MainActivity.this.getSupportActionBar().hide(); } else if (currentFirstVisibleItem < this.mLastFirstVisibleItem) { MainActivity.this.getSupportActionBar().show(); } this.mLastFirstVisibleItem = currentFirstVisibleItem; } }); 

Let me know if you need any help!

+73
Jul 20 '13 at 23:30
source share

You experience flickering as you hide / show the ActionBar available space for changing the layout of the content, which causes a relay. The index of the first visible position of the element also changes (you can check this by unloading mLastFirstVisibleItem and currentFirstVisibleItem .

You can handle flickering by letting ActionBar overlay the content layout. To enable blend mode for the action bar, you need to create a custom theme that extends the existing action bar theme and sets the android: windowActionBarOverlay property to true .

With this, you can eliminate the flicker, but the action bar will overlay your list contents. A simple solution for this is to set the top indent of the listview (or root layout) to the height of the action bar.

 <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="?android:attr/actionBarSize" /> 

Unfortunately, this will lead to constant filling at the top. The refinement of this solution is to add a title view to a list view that has height ? Android: attr / actionBarSize (and remove the previously installed top set)

+9
Mar 12 '14 at 10:16
source share

What you are looking for is called a Quick Return Pattern applied to the action bar. Google IO 2014 uses just that. I use it in one of my applications, you can check the source code of this Google application to find out how it got it. The BaseActivity class is where you have what you need, read the code and extract only this specific functionality. Enjoy the coding! :)

+8
Oct. 14 '14 at 23:02
source share

I am sure that this is not the best solution. But I have not yet found the best. Hope this will be helpful.

  static boolean scroll_down; ... mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (scroll_down) { actionBar.hide(); } else { actionBar.show(); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy > 70) { //scroll down scroll_down = true; } else if (dy < -5) { //scroll up scroll_down = false; } } }); 
+3
Nov 21 '14 at 14:43
source share

I have an idea that this is a good idea.

 listView.setOnScrollListener(new OnScrollListener() { int mLastFirstVisibleItem = 0; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_FLING: if (view.getId()==lv_searchresult_results.getId()){ final int currentFirstVisibleItem=lv_searchresult_results.getFirstVisiblePosition(); if(currentFirstVisibleItem>mLastFirstVisibleItem){ ObjectAnimator.ofFloat(toolbar, "translationY", -toolbar.getHeight()).start(); else if(currentFirstVisibleItem<(mLastFirstVisibleItem)){ ObjectAnimator.ofFloat(toolbar, "translationY", 0).start(); } mLastFirstVisibleItem= currentFirstVisibleItem; } if(lv_searchresult_results.getLastVisiblePosition() == myAdapter.getListMap().size()){ if(myAdapter.getListMap().size() < allRows&&!upLoading){ } } break; case OnScrollListener.SCROLL_STATE_IDLE: if (view.getFirstVisiblePosition()<=1){ ObjectAnimator.ofFloat(toolbar, "translationY", 0).start(); } if(lv_searchresult_results.getLastVisiblePosition() == myAdapter.getListMap().size()){ if(myAdapter.getListMap().size() < allRows&&!upLoading){ } } break; 
+1
May 17 '15 at 8:18
source share

I think everything will be fine.

 listView.setOnScrollListener(new OnScrollListener() { int mLastFirstVisibleItem = listView.getLastVisiblePosition(); boolean isScrolling = false; @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if(scrollState == 0) isScrolling = false; else if(scrollState == 1) isScrolling = true; else if(scrollState == 2) isScrolling = true; } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view.getId() == myTeamListView.getId()) { if(isScrolling) { final int currentFirstVisibleItem = myTeamListView.getLastVisiblePosition(); if (currentFirstVisibleItem > mLastFirstVisibleItem) { ((AppCompatActivity)getActivity()).getSupportActionBar().hide(); } else if (currentFirstVisibleItem < mLastFirstVisibleItem) { ((AppCompatActivity)getActivity()).getSupportActionBar().show(); } mLastFirstVisibleItem = currentFirstVisibleItem; } } } }); 
0
Mar 08 '16 at 13:21
source share

If you use the Layout coordinator, here is the trick.

 <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" /> 

The line app:layout_scrollFlags="scroll|enterAlways" will make our toolbar scroll the screen when the user scrolls down the list, and as soon as he starts scrolling, the toolbar will reappear.

-one
Mar 14 '17 at 8:17
source share



All Articles