In my application I got an activity with some kind of actionbar at the top and the listview below it. What I want to do - is to scroll it UP with the list, so it hides and then, when the list is being scrolled down - it should scroll down with the list, like it was just over the upper screen border. how can i achieve this functionality?

- 54,294
- 25
- 151
- 185

- 1,281
- 3
- 20
- 31
-
http://stackoverflow.com/questions/11494300/briefly-hiding-actionbar-without-resizing-activity – Nirav Ranpara Nov 26 '12 at 05:49
-
1@Graykos, can you choose a correct answer? – Jared Burrows Mar 19 '15 at 23:27
7 Answers
Updated 6/3/2015:
Google now supports this using the 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>
Documented here: https://developer.android.com/reference/android/support/design/widget/AppBarLayout.html
Original Answer:
Example similar to Google Play Music and Umano apps:
https://github.com/umano/AndroidSlidingUpPanel
Take a look at the code in this repository. As you slide the panel up, the ActionBar slides up as well.
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 example here:
https://play.google.com/store/apps/details?id=com.sothree.umano
ListView - without Libraries:
I recently wanted the same functionality and this works perfectly for me:
As the user scrolls upward, the ActionBar will be hidden in order to give the user the entire screen to work work with.
As the user scrolls downward and lets go, 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 - without 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 anymore help!

- 10,383
- 3
- 54
- 51

- 54,294
- 25
- 151
- 185
-
I like it. It seems to work, but there is an ugly flickering of the actionbar when it hides :-( – Ivan Morgillo Feb 12 '14 at 16:04
-
@hamen Yes, I have experienced the same issue. If you can find a better solution please let me know! – Jared Burrows Feb 12 '14 at 16:05
-
@JaredBurrows ne'mi's answer explains what's causing the flickering and how to avoid it. I recommend adding a "header" view with the Action Bar padding. – Dandre Allison Aug 05 '14 at 16:49
-
1
-
3That's works fine with plain listview ( listview header + acrion bar overlay) what about if my listview inside viewpager fragment with pagerrabstips? Iguess i need something like header view but for viewpager. Any suggestions? – Georgy Gobozov Dec 24 '14 at 13:16
-
@GeorgyGobozov I am not sure. I have used this method before with tabs just to hide the actionbar and keep the tabs similar to the google play store. – Jared Burrows Dec 24 '14 at 15:09
-
@Jared Burrows did you use actionbar overlay and padding for this? (like in answer below) Or you just called actionBar.hide()? – Georgy Gobozov Dec 25 '14 at 11:20
-
-
I used the plain listview solution, but hid my navigation tabs instead, with: if (currentFirstVisibleItem > mLastFirstVisibleItem) { actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); } else if (currentFirstVisibleItem < mLastFirstVisibleItem) { actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); } Not sure if there is a better way to do it, but it works nicely no flickering. – SammyT Apr 04 '15 at 06:23
-
1
-
Thanks @JaredBurrows, I will add it to my todo list to replace them. The google training docs look like they haven't been updated yet. http://developer.android.com/training/implementing-navigation/lateral.html#tabs – SammyT Apr 04 '15 at 06:43
-
what about if we have a SlidingTabLayout with a ViewPager? By using Actionbar Overlay we would hide the tabs! – splinter123 May 10 '15 at 14:52
-
-
@JaredBurrows still can't find an easy one. I thought it would be something standard, since it's the play app and many others... – splinter123 May 10 '15 at 15:49
-
@splinter123 Google always tends to add features in their own apps and the do not share their "special" tricks. This is why people create their own open source libraries on Github. – Jared Burrows May 10 '15 at 15:55
-
I've tried that cheesesquare sample, but at the first layout (toolbar with tablayout) the toolbar doesn't hide when I scrolled up the list..someone know why? – Dark Leonhart Jun 03 '15 at 09:41
-
@DarkLeonhart I would need to see your code. The toolbar needs to be in the `AppLayout` and in the `CoordinatorLayout`. – Jared Burrows Jun 04 '15 at 01:59
-
1@JaredBurrows Thanks, it worked already. The mistake is I'm still using recyclerview.jar from previous version (I'm still using Eclipse). The jar needs to be the latest version (v22). – Dark Leonhart Jun 05 '15 at 03:58
-
Is there any way we can use the coordinator layout to also hide a bottom bar or the FAB ? – Jul 06 '15 at 07:41
-
@Lupsaa Have you tried to use the layout with `app:layout_scrollFlags="scroll|enterAlways"` or something similar for your needs? – Jared Burrows Jul 06 '15 at 13:52
-
-
-
@VihaanVerma Did you even try anything? The code should be the same. – Jared Burrows Jul 23 '15 at 16:51
-
@JaredBurrows I did but with staggered gird you an array of positions. The view on the first position is pretty big so the actionbar in my case won't hide till the very first time is up for recycling. – Vihaan Verma Jul 23 '15 at 17:47
-
I am not sure. I have not used the `StaggeredGridLayoutManager ` – Jared Burrows Jul 23 '15 at 18:21
-
Please use ```addOnScrollListener(OnScrollListener)``` on RecyclerView because ```setOnScrollListener``` is deprecated. – Paolo Rotolo Sep 03 '15 at 15:50
-
Jared, I'm using the `Coordinator Layout` and the rest inside just like you use in the first code example, and I've a fragment with a `ListView` inside `Swipe Refresh Layout` inside a `Frame Layout`.. But the toolbar is not hiding when I scroll down this list.. what could the error be? – yat0 Dec 19 '15 at 20:30
-
@JaredBurrows: I tried the latest version of your answer but somehow it does not work with ListView scrolling. Any ideas? – Ishaan Oct 05 '16 at 10:56
-
@Ishaan I wrote this a while ago. Don't use `ListView`, use `RecyclerView`. – Jared Burrows Oct 05 '16 at 15:48
-
Thanks @JaredBurrows. The reason why I am using ListView is because I need fast scrolling which I am unable to achieve on recycler view. I referred https://github.com/danoz73/RecyclerViewFastScroller but it is very buggy. – Ishaan Oct 05 '16 at 16:00
You experience the flickering since by hiding/showing the ActionBar the available space for your content layout changes, which causes a relayout. With this the index of the first visible item's position changes as well (you can verify this by logging out mLastFirstVisibleItem and currentFirstVisibleItem.
You can cope with the flickering by letting the ActionBar overlay your content layout. To enable overlay mode for the action bar, you need to create a custom theme that extends an existing action bar theme and set the android:windowActionBarOverlay property to true.
With this you can eliminate the flickering but the action bar will overlay your listview's content. An easy solution to this is to set the listview's (or the root layout's) top padding to the action bar's height.
<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 result in a constant padding at the top. A refinement of this solution is to add a header view to the list view which has the height of ?android:attr/actionBarSize (and remove the top padding set previously)

- 346
- 2
- 4
-
2If you are using ActionBarSherlock or AppCompat, use android:paddingTop="?attr/actionBarSize" – Jared Burrows Sep 13 '14 at 19:14
-
I used your "A refinement" for my GridView. I forked and fixed a tiny lib. You can find it here: https://github.com/alter-ego/GridViewHeader – Ivan Morgillo Oct 07 '14 at 13:24
What you are looking for is called Quick Return pattern, applied to the Action Bar. Google IO 2014 app use exactly that. I use it in one of my apps, you can check the source code of that Google app to see how they got it. The BaseActivity class is where you have what you need, read the code and extract just that specific functionality. Enjoy coding! :)

- 6,958
- 2
- 31
- 42
-
-
@PiyushKukadiya the implementation is almost the same, just define a scroll listener for the Webview, here you have a full axample about how to do it: http://stackoverflow.com/questions/14752523/how-to-make-a-scroll-listener-for-webview-in-android – Diego Palomar Jan 24 '15 at 11:48
-
I did this but now I can't make the layout larger when the actionbar is hidden, how do I smoothly make the layout fit the space the actionbar once too – CQM Feb 04 '15 at 21:41
I am sure that it's not the best solution. But I haven't found a better one yet. Hope it will be helpfull.
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;
}
}
});

- 4,384
- 1
- 26
- 34
-
2Even I arrived at the same solution, but can't avoid flickering. Have you been able to remove the flickering caused by the show / hide? – jaibatrik Feb 28 '15 at 16:08
-
My last version was: if (dy > 40) { scroll_down = true; } else if (dy < -5) { scroll_down = false; } – Alexey Mar 07 '15 at 13:47
-
did anyone remove that flickering effect when we scroll slowly? – Shailendra Madda Aug 13 '18 at 14:41
-
I have a thought that it 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;

- 11
- 1
I think it will work 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;
}
}
}
});

- 1
- 2
If you are using a CoordinatorLayout, 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 app:layout_scrollFlags="scroll|enterAlways"
line will cause our Toolbar to scroll off the screen when the user scrolls down the list and as soon as he starts scrolling up the Toolbar will show up again.

- 1,794
- 20
- 37