How to detect if nested fling stopped entirely using CoordinatorLayout.Behavior? There is no such api which can give me callback when recycler view fling entirely stops.
I started down this rabbit hole while trying to hide a Floating Action Button (FAB) when a RecyclerView was being scrolled. The proper way to do this according to multiple sources is to extend FloatingActionButton.Behavior, override the onStartNestedScroll
and onStopNestedScroll
methods, and hook your behavior up to the FAB, e.g. app:layout_behavior="com.justingarrick.ui.ScrollAwareFabBehavior"
. This works for normal (slow) scroll events, but onStopNestedScroll
is not called when a fling ends.
Currently, there seem to be a number of open issues with flinging and scroll behaviors; the workaround for me was to implement an OnScrollListener
for my RecyclerView and just change the state of the FAB programmatically, e.g.
public class MyFragment extends Fragment {
@Bind(R.id.account_list) RecyclerView recyclerView;
@Bind(R.id.button_fab) FloatingActionButton fab;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_accounts, container, false);
ButterKnife.bind(this, view);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_DRAGGING)
fab.hide(); // or hideFab(), see below
else if (newState == RecyclerView.SCROLL_STATE_IDLE)
fab.show(); // or showFab(), see below
}
});
return view;
}
}
UPDATE: This works correctly 99% of the time, but if you use the show()
and hide()
methods from version 22.2.1 of the design library, you'll run into problems when you try to scroll up at the top of your RecyclerView or down at the bottom of your RecyclerView because the recycler view is switching states from RecyclerView.SCROLL_STATE_DRAGGING
to RecyclerView.SCROLL_STATE_IDLE
so quickly that it creates a race condition in FloatingActionButtonHoneycombMr1#show()
. So, to fix this (sigh), you either need to switch to setVisibility()
calls if you don't care about the animations, or re-implement the animations without the race condition, e.g.
private void hideFab() {
fab.animate().scaleX(0.0F).scaleY(0.0F).alpha(0.0F).setDuration(200L).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
fab.setVisibility(View.GONE);
}
});
}
private void showFab() {
fab.animate().scaleX(1.0F).scaleY(1.0F).alpha(1.0F).setDuration(200L).setInterpolator(new FastOutSlowInInterpolator()).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
fab.setVisibility(View.VISIBLE);
}
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With