I wnat to show and hide the Android ActionBar when the user scrolls the screen. I found some examples, like this question in SO. But the code showed in this question and its answer makes the action hides after the list have scrolled some pixels, and I want to make this scroll like the Inbox App by Google, that is the action bar is pulled by the Layout according to the user scroll the screen up or down, in other words, I want to show/hide the action bar at the same time the user scroll down/up.
Someone face a problema like this? Some idea?
super simple:
- ditch the
ListView
. ListView is the past. Use RecyclerView
instead.
- add a
RecyclerView.OnScrollListener
to it, to get pixel-by-pixel scroll.
- use a
Toolbar
on your activity layout. So you can control the position of it.
- call
setTranslationY(val)
on your Toolbar
to "scroll" it with the RecyclerView
.
a few links with the docs for the mentioned classes:
- http://android-developers.blogspot.de/2014/10/appcompat-v21-material-design-for-pre.html
- https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html
- https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener.html
- http://developer.android.com/reference/android/widget/Toolbar.html
- https://developer.android.com/reference/android/view/View.html#setTranslationY(float)
I created a solution based answer of @Budius and this link
First add this class
public class HidingRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
private final int UP = 0;
private final int DOWN = 1;
private final int margin = 5;
private View mView;
RecyclerView.LayoutManager mLayoutManager;
private float currentPoint = 0;
private int lastDirection = 1;
public HidingRecyclerViewScrollListener(View view, LinearLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
mView = view;
}
public HidingRecyclerViewScrollListener(View view, GridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
mView = view;
}
public HidingRecyclerViewScrollListener(View view, StaggeredGridLayoutManager layoutManager) {
this.mLayoutManager = layoutManager;
mView = view;
}
public int getFirstVisibleItem(int[] firstVisibleItemPositions) {
int minSize = 0;
for (int i = 0; i < firstVisibleItemPositions.length; i++) {
if (i == 0) {
minSize = firstVisibleItemPositions[i];
} else if (firstVisibleItemPositions[i] < minSize) {
minSize = firstVisibleItemPositions[i];
}
}
return minSize;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
float nextPoint = currentPoint + dy;
if (nextPoint < 0) {
nextPoint = 0;
}
if (nextPoint > viewSize()) {
nextPoint = viewSize();
}
lastDirection = nextPoint >= currentPoint ? UP : DOWN;
currentPoint = nextPoint;
mView.setTranslationY(-currentPoint);
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (lastDirection == UP) {
if (getFirstVisibleItem() > 0) {
currentPoint = viewSize();
}
}
if (lastDirection == DOWN) {
//Volta para origem
currentPoint = 0;
}
mView.animate().translationY(-currentPoint);
}
}
private int getFirstVisibleItem() {
int firstVisibleItem = 0;
if (mLayoutManager instanceof StaggeredGridLayoutManager) {
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findFirstVisibleItemPositions(null);
firstVisibleItem = getFirstVisibleItem(lastVisibleItemPositions);
} else if (mLayoutManager instanceof LinearLayoutManager) {
firstVisibleItem = ((LinearLayoutManager) mLayoutManager).findFirstVisibleItemPosition();
} else if (mLayoutManager instanceof GridLayoutManager) {
firstVisibleItem = ((GridLayoutManager) mLayoutManager).findFirstVisibleItemPosition();
}
return firstVisibleItem;
}
private int viewSize() {
return mView.getHeight() + margin;
}
}
Is simple to use, only add using addOnScrollListener of your recyclerView
recyclerView = (RecyclerView) view.findViewById(R.id.mRecyclerView );
layoutManager = new LinearLayoutManager(getContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.addOnScrollListener(new HidingRecyclerViewScrollListener(mView, layoutManager));
mView is the view you want to control
You can user this class with LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager (but i never test with GridLayoutManager)
In RecyclerView use the code below to the list does not stay below the object you want to control, this code is simpler and better to test, but use a Hearder in RecyclerView as is said in the link above has a better result.
android:clipToPadding="false"
android:paddingTop="@dimen/outher_view_dimem"
If you using SwipeRefreshLayout use code below to show ProgressBar
swipeRefreshLayout.setProgressViewOffset(true, 0, mViewHeight + actionBarHeight);