I have a View and a RecyclerView housed in a LinearLayout. What I want to achieve is something like this:
https://material.google.com/patterns/scrolling-techniques.h
You have to use Coordinator Layout with the CollapsingToolbarLayout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="210dp"
android:stateListAnimator="@animator/appbar_always_elevated" //I put this here because I want to have shadow when is open, but you have to create the xml file.
android:background="@color/WHITE">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:collapsedTitleTextAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
app:expandedTitleMarginStart="72dp"
app:expandedTitleTextAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
app:layout_scrollFlags="scroll|exitUntilCollapsed"> //HERE you should take a look what you want your collapse bar do.
<Here you put the content for you collapse bar, like a ImageView>
<android.support.v7.widget.Toolbar //This is the size of your fixed bar when you collapse, even here you can put a back button, for example
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="40dp"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/main_home_list_swipe"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" >
<android.support.v7.widget.RecyclerView
android:id="@+id/main_home_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout >
Obs: the comments will give errors if you put on a xml file. Is on propose so you will remember to read hahahah
To achieve toolbar to expand and collapse smoothly you can apply translate animation or use CoordinatorLayout with AppBarLayout and Toolbar.
Animation : First you have to detect scroll up and scroll down on your RecyclerView. To do so you can set “setOnScrollListener” on your RecyclerView. Once you have both scroll up and scroll down, simply apply animation.
Code:
rvHomeList.setOnScrollListener(new RecyclerView.OnScrollListener() {
int verticalOffset;
boolean scrollingUp;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
if (scrollingUp) {
Log.e("onScrollStateChanged", "UP");
if (verticalOffset > llTop.getHeight()) {
toolbarAnimateHide();
}
} else {
Log.e("onScrollStateChanged", "down");
if (llTop.getTranslationY() < llTop.getHeight() * -0.6 && verticalOffset > llTop.getHeight()) {
toolbarAnimateHide();
} else {
toolbarAnimateShow(verticalOffset);
}
}
}
}
@Override
public final void onScrolled(RecyclerView recyclerView, int dx, int dy) {
verticalOffset += dy;
scrollingUp = dy > 0;
int toolbarYOffset = (int) (dy - llTop.getTranslationY());
llTop.animate().cancel();
if (scrollingUp) {
Log.e("onScrolled", "UP");
if (toolbarYOffset < llTop.getHeight()) {
llTop.setTranslationY(-toolbarYOffset);
} else {
llTop.setTranslationY(-llTop.getHeight());
}
} else {
Log.e("onScrolled", "down");
if (toolbarYOffset < 0) {
llTop.setTranslationY(0);
} else {
llTop.setTranslationY(-toolbarYOffset);
}
}
}
});
Animation Methods:
private void toolbarAnimateShow(final int verticalOffset) {
if (!isShowing) {
isShowing = true;
llTop.animate()
.translationY(0)
.setInterpolator(new LinearInterpolator())
.setDuration(180)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
llTop.setVisibility(View.VISIBLE);
isShowing = false;
}
});
}
}
private void toolbarAnimateHide() {
if (!isHidding) {
isHidding = true;
llTop.animate()
.translationY(-llTop.getHeight())
.setInterpolator(new LinearInterpolator())
.setDuration(180)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
llTop.setVisibility(View.GONE);
isHidding = false;
}
});
}
}
CoordinatorLayout with AppBarLayout and Toolbar: By using coordinatorLayout with appBarLayout and toolbar, and set the scroll flag used within the attribute app:layout_scrollFlags to achieve the scroll effect. It must be enabled for any scroll effects to take into effect. This flag must be enabled along with enterAlways, enterAlwaysCollapsed, exitUntilCollapsed, or snap.
Code:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/llBase"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbarContainer"
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="@dimen/_40sdp"
android:gravity="center"
android:theme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways">
<include
layout="@layout/top_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<RelativeLayout
android:id="@+id/rlMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
Try this:- I also want this kind of animation on custom view and i have achieved it this way.
public class TestActivity extends AppCompatActivity {
private static final int HIDE_THRESHOLD = 20;
//this is you custom layout it is any thing.
LinearLayout customLayout;
private int scrolledDistance = 0;
private boolean controlsVisible = true;
private RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.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);
scrolledDistance = dy;
if (scrolledDistance > HIDE_THRESHOLD && controlsVisible) {
hideViews();
controlsVisible = false;
} else if (scrolledDistance < -HIDE_THRESHOLD && !controlsVisible) {
showViews();
controlsVisible = true;
}
}
});
}
private void hideViews() {
customLayout.animate().translationY(-customLayout.getHeight()).setInterpolator(new AccelerateInterpolator(2));
}
private void showViews() {
customLayout.animate().translationY(0).setInterpolator(new DecelerateInterpolator(2));
}
}
Edit - 1
for ScrollView
try this listener
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
if (scrolledDistance > HIDE_THRESHOLD && controlsVisible) {
hideViews();
controlsVisible = false;
scrolledDistance = 0;
} else if (scrolledDistance < -HIDE_THRESHOLD && !controlsVisible) {
showViews();
controlsVisible = true;
scrolledDistance = 0;
}
}
});
Hope it also helps you...
You need to use CoordinatorLayout to achieve what you want. You could find all needed information in this tutorial.