In this link there is the solution to ocular and show the fab button FloatingActionButton
depending on the scroll
But I would like it when I hide and show the fab button I did it with an animation slide Up and Down:
You can do it in two ways, using a class that extends from FloatingActionButton.Behavior
and linking it with the view of Floating Action Button
in XML
or programming it directly in RecyclerView
.
I'll show you the two ways and you choose the one you like best.
FIRST METHOD
When I looked for how to do just what you are asking, everything that appeared used the same method. They created a new java class and extended FloatingActionButton.Behavior
to detect the movement of ListView
or RecyclerView
(what you use) and then link this same class with the view of Floating Action Button
( FAB
) of the next Form:
Class FABMove.java
:
public class FABMove extends FloatingActionButton.Behavior {
public FABMove(Context context, AttributeSet attrs) {
super();
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0) {
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) child.getLayoutParams();
int margin = layoutParams.bottomMargin;
child.animate().translationY(child.getHeight() + margin).setInterpolator(new LinearInterpolator()).setDuration(1000).start();
} else if (dyConsumed < 0) {
child.animate().translationY(0).setInterpolator(new LinearInterpolator()).setDuration(1000).start();
}
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
}
And now, you just have to go to the file XML
where you have declared the FAB
and add a CoordinatorLayout
encapsulating your RecyclerView
and the FAB
and to this you add the property app:layout_behavior
that links to your java class:
<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.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_anchor="@+id/recycler_view"
app:layout_anchorGravity="bottom|end"
app:layout_behavior="com.victoria.fabsmove.FABMove" />
</android.support.design.widget.CoordinatorLayout>
Ready!
SECOND METHOD:
This method, for me, I see relatively simple, much more than the first because you do not have to create so many things. You simply have to add the function addOnScrollListener()
to RecyclerView
and overwrite the method onScrolled()
to detect the movement of the list.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy){
if (dy > 0)
// Puedes ocultarlo simplemente
//fab.hide();
// o añadir la animación deseada
fab.animate().translationY(fab.getHeight() +
getResources().getDimension(R.dimen.fab_margin))
.setInterpolator(new LinearInterpolator())
.setDuration(1000); // Cambiar al tiempo deseado
else if (dy < 0)
//fab.show();
fab.animate().translationY(0)
.setInterpolator(new LinearInterpolator())
.setDuration(1000); // Cambiar al tiempo deseado
}
});
With this, everything would be ready. If you have any questions, notify us immediately.
Even so, the answer given by our colleague Andres Gillermo Castellanos A ( link ), because in addition you teach yourself to create menus directly in FAB
and it is very interesting.
Good luck with your app!
My solution using FloatingActionButton.Behavior
adapting the response code @Vicky_Vicent
I add a flag
to know if the animation is in progress, to avoid animation overload.
public class AboutFabScrollBehavior extends FloatingActionButton.Behavior {
private boolean startAnimation = false;
public AboutFabScrollBehavior(Context context, AttributeSet attributeSet) {
super();
}
@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, final FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
// User scrolled down and the FAB is currently visible -> hide the FAB
if (!startAnimation) {
Interpolator interpolador = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
interpolador = AnimationUtils.loadInterpolator(MyApplication.getAppContext(),
android.R.interpolator.fast_out_linear_in);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
child.animate()
//.translationYBy(0f)
.translationY(child.getHeight() +
child.getContext().getResources().getDimension(R.dimen.fab_margin))
.setInterpolator(interpolador)
.setDuration(child.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime))
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
child.setVisibility(View.GONE);
startAnimation = false;
}
})
.start();
}
startAnimation = true;
}
} else if (dyConsumed < 0 && child.getVisibility() == View.GONE) {
// User scrolled up and the FAB is currently not visible -> show the FAB
if (!startAnimation) {
child.setVisibility(View.VISIBLE);
Interpolator interpolador = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
interpolador = AnimationUtils.loadInterpolator(MyApplication.getAppContext(),
android.R.interpolator.fast_out_linear_in);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
child.animate()
// .translationYBy(150f)
.translationY(0f)
.setInterpolator(interpolador)
.setDuration(child.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime))
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
startAnimation = false;
}
})
.start();
}
Animation animation = AnimationUtils.loadAnimation(MyApplication.getAppContext(),
R.anim.fade_in);
child.startAnimation(animation);
}
}
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
// Ensure we react to vertical scrolling
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
|| super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
//return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;
}
}