Google have released Design library, I am using
compile 'com.android.support:design:22.2.1'
However I cant see any code examples of how to use this library and how to animate the FAB
bar on scroll. I guess I can listen for scroll events on the ListView
and then animate the button myself, but is this not baked into the API (is this not the point of this support library).
Is there examples for this ?
If you're using RecyclerView
and you're looking for something simple, you can try this:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy){
if (dy > 0)
fabAddNew.hide();
else if (dy < 0)
fabAddNew.show();
}
});
By replacing 0
with a constant, you can adjust the sensitivity of triggering, providing smoother experience
Making a component react to scroll events is most easily done with a custom CoordinatorLayout.Behavior, as they receive scroll events automatically when you override onStartNestedScroll().
An example Behavior that hides and shows the FAB on scroll found in this FABAwareScrollingViewBehavior, built on top of cheesesquare:
public class FABAwareScrollingViewBehavior
extends AppBarLayout.ScrollingViewBehavior {
public FABAwareScrollingViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent,
View child, View dependency) {
return super.layoutDependsOn(parent, child, dependency) ||
dependency instanceof FloatingActionButton;
}
@Override
public boolean onStartNestedScroll(
final CoordinatorLayout coordinatorLayout, final View child,
final View directTargetChild, final View target,
final int nestedScrollAxes) {
// Ensure we react to vertical scrolling
return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
|| super.onStartNestedScroll(coordinatorLayout, child,
directTargetChild, target, nestedScrollAxes);
}
@Override
public void onNestedScroll(
final CoordinatorLayout coordinatorLayout, final View child,
final View target, final int dxConsumed, final int dyConsumed,
final int dxUnconsumed, final int dyUnconsumed) {
super.onNestedScroll(coordinatorLayout, child, target,
dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
if (dyConsumed > 0) {
// User scrolled down -> hide the FAB
List<View> dependencies = coordinatorLayout.getDependencies(child);
for (View view : dependencies) {
if (view instanceof FloatingActionButton) {
((FloatingActionButton) view).hide();
}
}
} else if (dyConsumed < 0) {
// User scrolled up -> show the FAB
List<View> dependencies = coordinatorLayout.getDependencies(child);
for (View view : dependencies) {
if (view instanceof FloatingActionButton) {
((FloatingActionButton) view).show();
}
}
}
}
}
Where your scrolling view would have app:layout_behavior="com.support.android.designlibdemo.FABAwareScrollingViewBehavior"
instead of app:layout_behavior="@string/appbar_scrolling_view_behavior"
However you can replace hide()
and show()
with any action if you want. Details on how this was done can be found in this post and the follow up post for v22.2.1 and the follow up post for v25.1.0.
Note that this, like all scrolling behaviors of the Design Library, require that your view supports nested scrolling, which currently limits you to NestedScrollView, RecyclerView - ListView
and ScrollView
only work on API21+ devices.
If you're NOT using a RecycleView (that is, just regular ScrollView) this will do the trick:
mScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
if (mScrollView.getScrollY() > oldScrollYPostion) {
fab.hide();
} else if (mScrollView.getScrollY() < oldScrollYPostion || mScrollView.getScrollY() <= 0) {
fab.show();
}
oldScrollYPostion = mScrollView.getScrollY();
}
});
Don't forget to declare:
private int oldScrollYPostion = 0;
inside you class.
Using CoordinatorLayout is best way.
Hoever if you want to attach listener to ListView or RecyclerView you also can do that.
I think is more customizable.
Here is my example on git hub.
Github Project: Hide FAB(material Library) with listview
The @ianhanniballake is working fine but the methods onStartNestedScroll()
and onNestedScroll()
were deprecated. Here is the updated version:
public class FabAwareScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {
public FabAwareScrollingViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
return super.layoutDependsOn(parent, child, dependency) ||
dependency instanceof FloatingActionButton;
}
@Override
public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout,
@NonNull View child, @NonNull View directTargetChild,
@NonNull View target, int axes, int type) {
// Ensure we react to vertical scrolling
return axes == ViewCompat.SCROLL_AXIS_VERTICAL ||
super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, axes, type);
}
@Override
public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout,
@NonNull View child, @NonNull View target, int dx, int dy,
@NonNull int[] consumed, int type) {
super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
if (dy > 0) {
// User scrolled down -> hide the FAB
List<View> dependencies = coordinatorLayout.getDependencies(child);
for (View view : dependencies) {
if (view instanceof FloatingActionButton) {
((FloatingActionButton) view).hide();
}
}
} else if (dy < 0) {
// User scrolled up -> show the FAB
List<View> dependencies = coordinatorLayout.getDependencies(child);
for (View view : dependencies) {
if (view instanceof FloatingActionButton) {
((FloatingActionButton) view).show();
}
}
}
}
}
Also there is a very good post by @ianhanniballake on this topic: Intercepting everything with CoordinatorLayout Behaviors
recyclerView.setOnFlingListener(new RecyclerView.OnFlingListener() {
@Override
public boolean onFling(int velocityX, int velocityY) {
if (velocityY < 0)
mScrollCallbacks.showUI();
//Code to hide the UI, I have a custom one that slides down the nav bar and the fab
else if (velocityY > 0)
mScrollCallbacks.hideUI();
//Code to show the UI
return false;
}
});
This works very well