I have an issue when using onSingleTapUp of GestureDetector and onTouchEvent of the View together. Both onSingleTapUp and ACTION_DOWN/UP sections of the onTouchEvent manipulate same object set before drawing on the canvas.
I want to stop onTouchEvent continuing if it is clearly a single tap. I am not sure how to avoid this. Should I use synchronize instead?
#Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
//code here
case MotionEvent.ACTION_MOVE:
//code here
case MotionEvent.ACTION_UP:
//code here
}
//try this:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
return gestureDetector.onTouchEvent(ev);
}
Related
I'm trying to have a scrolling MapView inside of a RecyclerView, therefore I'm setting requestDisallowInterceptTouchEvent() before and after the TouchEvent.
The odd thing is: this does work if I set it in the dispatchTouchEvent() method, but it doesn't work if I do the same in the onTouchEvent() method.
Can somebody explain why I cannot set this in onTouchEvent()?
Working:
public class WorkingScrollableListItemMapView extends MapView {
// constructors
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// Stop parents from handling the touch
this.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow parents from handling the touch
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.dispatchTouchEvent(ev);
}
}
Not working:
public class NotWorkingScrollableListItemMapView extends MapView {
// constructors
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
// Allow parents from handling the touch
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_DOWN:
// Stop parents from handling the touch
this.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return super.onTouchEvent(ev);
}
}
Call sequence for handling an event are somewhat in this order:
onInterceptTouchEvent, onDispatchTouchEvent, dispatchTouchEvent, onTouchEvent.
That, to me, indicates that the onTouchEvent is the very last step in processing an event. It would be too late to manipulate where & whom handles the event at the very last step. What does the source code say if you look at the earlier methods for handling the event?
If I touch down on a View, and then move passed its borders onto another View, the touch event ends (cancels). How can I continue processing the touch event on the next View without having to lift my finger up and retouch down onto the adjacent View, given that this is all happening within a ScrollView?
To prevent the ScrollView from scrolling when I move on the views, I have this system set up:
mScrollView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return mScrollingDisabled;
}
});
mTouchableView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mScrollingDisabled=true;
break;
case MotionEvent.ACTION_CANCEL:
mScrollingDisabled=false;
break;
case MotionEvent.ACTION_MOVE:
mScrollingDisabled=true;
break;
case MotionEvent.ACTION_UP:
mScrollingDisabled=false;
}
return false;
}
});
I'm trying to catch the ACTION_UP and ACTION_CANCEL on my RecyclerView, but I want every other event to be caught by it's children, but it seems the child that caught the first event is the only one that catches all the following ones. Here my code for the intercept event.
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
boolean takeEventControl = false;
switch (e.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
takeEventControl = true;
break;
case MotionEvent.ACTION_MOVE:
// Some processing
takeEventControl = false;
break;
}
return takeEventControl;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
// Some code
}
And here is my code for the child views
#Override
public boolean onTouch(final View view, final MotionEvent event) {
switch (e.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
//Some processing
break;
case MotionEvent.ACTION_MOVE:
//Some processing
break;
}
return true;
}
I already tested it and find that if I return true the first time the onInterceptTouchEvent is triggered the onTouchEvent is called successfully, but in my code I need to call the child onTouch when the event action is ACTION_DOWN or ACTION_MOVE, and the onTouchEvent on ACTION_UP or ACTION_CANCEL but the last one is never called, I hope someone could explain me what's happening here.
To avoid having a view control touches after the ACTION_DOWN, have all views return false in their onTouch for ACTION_DOWN. You can then return true for other touch events that are truly being handled.
The reason behind this is the first view to return true for ACTION_DOWN will be the only view to receive future onTouch calls until after an ACTION_UP or ACTION_CANCEL is received.
I want to get activity or any control element's touch counts.
Like Android 4.2 on nexus Developer options Enable while touching 7 times.
What is the suitable event to handle it ?
You are getting 2 count's because the touch event are called every time a touch event is snet, like tump down and tump up (for example)
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
switch (action) {
case MotionEvent.ACTION_DOWN:
//add here the counter if you want when screen pressed
break;
case MotionEvent.ACTION_UP:
//add here the counter if you want when touch released
break;
default:
return super.onTouchEvent(event);
}
}
You can use a View.OnTouchListener, overriding the onTouch method :
#Override
public boolean onTouch(final View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// increment counter
break;
}
}
I'm trying to create a custom GridView but i'm having troubles with the touch listeners.
What i want to do:
Create a GridView with custom Views.
Longpress on an item so it becomes 'editable'.
Drag the view horizontal or vertical to move it's position in the GridView.
Here's where i'm having trouble:
I'm implementing GestureDetector.OnGestureListener for the longpress functions, because for some reason using the gridview.setOnItemLongClickListener() isn't working when overriding the onTouchEvent() of the GridView itself (Which i need for the dragging part). So everything is fine at this point. Now i only need to know when the longpress is finished. So i though: "Well this shouldn't be hard." I couldn't have be more wrong. I've fiddled around for quite some time with this and it looks like using different touch events isn't helping me :/
When stepping through the onTouchEvent() i noticed that only 1 action is given: MotionEvent.ACTION_DOWN. So what am i doing wrong? i need the MotionEvent.ACTION_UP...
Found the culprit:
i was doing something like this
#Override
public boolean onTouchEvent(MotionEvent event) {
// Give everything to the gesture detector
boolean retValue = gestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE :
onMove();
break;
case MotionEvent.ACTION_UP :
onUp();
break;
case MotionEvent.ACTION_CANCEL:
onCancel();
break;
}
return retValue;
}
i think retValue was always returning false so no other events were triggered.
this fixed the issue:
#Override
public boolean onTouchEvent(MotionEvent event) {
// Give everything to the gesture detector
gestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE :
onMove();
break;
case MotionEvent.ACTION_UP :
onUp();
break;
case MotionEvent.ACTION_CANCEL:
onCancel();
break;
}
return true;
}