Reputation: 33876
I have a RecyclerView where I have added different actions that can be performed on the list items. Particularly, DragDrop
and SwipeDismiss
. DragDrop
is initiated by long-press, and SwipeDismiss
is initiated by swiping. I have to watch for scroll events to block those actions from happening. It is annoying to be scrolling then it suddenly switched to dragging. Before I would add an OnScrollListener
to handle this.
This is what I did before:
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if(newState == RecyclerView.SCROLL_STATE_IDLE){
drag.setCurrentAction(IDLE);
} else {
drag.setCurrentAction(SCROLL);
}
}
No longer will work
I recently added CoordinatorLayout for collapsable toolbars. Now when scrolling up, drag
wont get set to SCROLL
until the toolbar has been collapsed. I tried to create my own behavior, but that would replace my current behavior I am using; @string/appbar_scrolling_view_behavior
. This removed the behaviors I wanted for the toolbar and didn't work to notify my drag
state.
What I have tried:
@Override
public boolean onStartNestedScroll(CoordinatorLayout cl, CollapsingToolbarLayout child, View directTargetChild,
View target, int nestedScrollAxes) {
if (nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL) {
if (drag.getCurrentAction().ordinal() < SCROLL.ordinal()) {
/* No actions have started and we are scrolling. set the new action */
drag.setCurrentAction(SCROLL);
}
return true;
}
return super.onStartNestedScroll(cl, child, directTargetChild, target, nestedScrollAxes);
}
@Override
public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, CollapsingToolbarLayout child, View target) {
super.onStopNestedScroll(coordinatorLayout, child, target);
if (drag.getCurrentAction() == SCROLL) {
drag.setCurrentAction(INVALID);
}
}
So my question
How do I listen for those scroll changes on my recycler view that are being intercepted by the CoordinatorLayout
? Is a Behavior the correct way?
Upvotes: 5
Views: 3398
Reputation: 234
have you tried to add a touchEvent listener, then deactivate the interceptors events for the parent viewgroup holder? I reckon that returns to the child the control of any touch event you want to handle.
scrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Disallow the touch request for parent scroll on touch of child view
v.getParent().requestDisallowInterceptTouchEvent(true);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
v.getParent().requestDisallowInterceptTouchEvent(false);
}
return false;
}
});
Upvotes: 1
Reputation: 200080
You should instead use ItemTouchHelper as detailed in this blog post.
It contains methods such as
onMove(RecyclerView, ViewHolder, ViewHolder)
onSwiped(ViewHolder, int)
Which allow you to implement drag and drop as well as swipe to dismiss without writing custom Behaviors or touch event handling.
Upvotes: -1