I have a View that is inside ScrollView
. I want to call some method every 80ms as long as the user is holding that View pressed. This is what i have implemented:
final Runnable vibrate = new Runnable() {
public void run() {
vibrate();
}
};
theView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
final ScheduledFuture<?> vibrateHandle =
scheduler.scheduleAtFixedRate(vibrate, 0, 80, MILLISECONDS);
vibrateHanlers.add(vibrateHandle);
return true;
}
if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL
|| motionEvent.getAction() == MotionEvent.ACTION_UP) {
clearAllScheduledFutures();
return false;
}
return true;
}
});
The problem is, ACTION_CANCEL
is called for the smallest move of the finger. I know that is because the View
is inside ScrollView
, but i am not sure what are my options here. Do i create custom ScrollView
, and try to find if the desired View is touched and disable the touch event for the ScrollView
? Or maybe, disable the touch event for SrollView
for small threshold of moving? Or something else?
Here it is how i fixed it.
I created custom ScrollView
:
public class MainScrollView extends ScrollView {
private boolean shouldStopInterceptingTouchEvent = false;
public void setShouldStopInterceptingTouchEvent(boolean shouldStopInterceptingTouchEvent) {
this.shouldStopInterceptingTouchEvent = shouldStopInterceptingTouchEvent;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (shouldStopInterceptingTouchEvent)
return false;
else
return super.onInterceptTouchEvent(ev);
}
}
And in the onTouchEvent:
theView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
svMain.setShouldStopInterceptingTouchEvent(true);
final ScheduledFuture<?> vibrateHandle =
scheduler.scheduleAtFixedRate(vibrate, 0, 80, MILLISECONDS);
vibrateHanlers.add(vibrateHandle);
return true;
}
if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL
|| motionEvent.getAction() == MotionEvent.ACTION_UP) {
svMain.setShouldStopInterceptingTouchEvent(false);
clearAllScheduledFutures();
return false;
}
return true;
}
});
So, instead of determining when to stop intercepting touchEvent
in the ScrollView
, i am deciding that in the onTouchListener
of the View
.