The correct way would be intercepting user's touch when you scrolling pragmatically. That would require you to extend ScrollView
overriding scrollTo
and onInterceptTouchEvent
methods and disable user touch while list is scrolling, returning touch after scroll is complete.
So the sequence would be like this:
- Call
scrollTo
to scroll to specific position
- Enable a flag to disable touch events and begin scrolling
- When scroll is finished and state changed to idle disable flag
P.S: I can provide code example but it appears you have more expertise than me in writing codes. Cheers!
Here a code snippet:
import android.content.Context;
import android.support.v4.widget.NestedScrollView;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class MyScrollView extends NestedScrollView {
public static final int MAX_SCROLL_FACTOR = 1;
boolean isAutoScrolling;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void scrollTo(int x, int y) {
isAutoScrolling = true;
super.scrollTo(x, y);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (isAutoScrolling)
return super.onInterceptTouchEvent(event);
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isAutoScrolling)
return super.onTouchEvent(event);
return false;
}
@Override
protected void onScrollChanged(int x, int y, int oldX, int oldY) {
super.onScrollChanged(x, y, oldX, oldY);
if (isAutoScrolling) {
if (Math.abs(y - oldY) < MAX_SCROLL_FACTOR || y >= getMeasuredHeight() || y == 0
|| Math.abs(x - oldX) < MAX_SCROLL_FACTOR || x >= getMeasuredWidth() || x == 0) {
isAutoScrolling = false;
}
}
}
}