I have a simple layout:
<CustomFrameLayout>
<ListView />
</CustomFrameLayout>
In my CustomFrameLayout, I am overriding:
onInterceptTouchEvent(MotionEvent event);
and returning false. When scrolling the ListView, the onInterceptTouchEvent receives the ACTION_DOWN and the first ACTION_MOVE event. Then, the ListView seems to take over and onInterceptTouchEvent fails to receive the following ACTION_MOVE events.
This goes against what the documentation states:
For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)
I have looked into requesting touch events to not be intercepted at the ListView level.
requestDisallowInterceptTouchEvent(boolean disallowIntercept)
This does not seem to have any effect. Should I be calling this on the ListView cell view's as well? Is there something else I am missing? I am testing on Android 4.4
Thanks.
you should return true in onInterceptTouchEvent(MotionEvent event);
true indicates that you are willing to receive further touch actions where as false indicates you are not interested further actions...
I have decided to override this method instead. Here, I can guarantee that I can intercept all touch events before they are dispatched to and potentially consumed by the child views.
dispatchTouchEvents(MotionEvent event);
Related
Does it matter if i return true or false in onTouch() of an OnTouchListener?
I can't see any difference between returning true or false in this example: Android Swipe on List
The return value determines if you consumed the touch event.
In other words true means that this touch event is interesting to you and all follow up calls of this touch event like ACTION_MOVE or ACTION_UP will be delivered to you.
If you return false than the touch event will be passed to the next View further up in the view hierarchy and you will receive no follow up calls. The touch event will continue to be passed further up the view hierarchy until someone consumes it.
If you have any further questions please feel free to ask!
In my DynamicListView class, I need to handle two events: onTouchEvent and OnItemLongClick event. My expectation is that the onTouchEvent is called before the OnItemLongClick event. However, this is not the case. The OnItemLongClick event is handled without any call to the OnTouchEvent. Is there anyway to specify the order of these handlers ? I need to get the coordinates of the touch event first before handling the OnItemLongClick event.
Try to override dispatchTouchEvent(MotionEvent ev) in your DynamicListView.
I want my callback to be fired on every touch event for a particular view. I've found similar question: View.onTouchEvent only registers ACTION_DOWN event by there is no direct answer.
If true is returned from onTouch() then further events belonging to the same touch (eg. ACTION_MOVE) are reported, but flow is disrupted and normal event processing does not happen (eg. View is not entering in pressed state).
If false or super.onTouchEvent is returned then only ACTION_DOWN is reported but not other actions and normal processing happens correctly (eg. View is entering in pressed state). Unfortunately other callbacks like onInterceptTouchEvent() aren't called as well.
I want to be both notified on all touch events (ACTION_DOWN, ACTION_MOVE and so on) and not disrupt normal processing (eg. View should enter correct state when touched). How to achieve this behavior?
You can try to extend your particular View and overwrite dispatchTouchEvent like this
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
handleTouch(ev);
return super.dispatchTouchEvent(ev);
}
And implement handleTouch to do whatever you want to do without disrupting the normal flow.
ths sdk said:
3、For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent().
4、If you return true from here, you will not receive any following events: the target view will receive the same event but with the action ACTION_CANCEL, and all further events will be delivered to your onTouchEvent() method and no longer appear here.
But when i use this method,no matter what onInterceptTouchEvent() returns ,it does the same work! And never did MotionEvent.ACTION_MOVE or MotionEvent.ACTION_UP been captured by this method. Can anybody help me figure it out?
ths!
Normally the touch goes from most upper view to the lowest through onInterceptTouchEvent and then it goes back via onTouchEvent.
If you return true in onInterceptTouchEvent you forbid it to continue and the view where you returned true is the last one to receive the touch, you consume it
You can also disallow your parent view to consume the event by
requestDisallowInterceptTouchEvent(true);
When none of the children of your view return true in onTouchEvent, onInterceptTouchEvent will ONLY be called for MotionEvent.ACTION_DOWN.
Here is a complete description of the MotionEvent processing.
I want to listen to touch events for a viewFlipper. I've been able to listen to touch events in my activity and then modify the viewFlipper but these events are fired wherever the user is within the activity and I need to capture touch events specifically on the viewFlipper. I have tried adding setOnTouchListener but it is not called. I'm assuming the viewFlippers children (webviews) are 'consuming' the touch events.
One solution would be to setOnTouchListener's to each of the webviews but this feels like a hack. Does anyone know another way?
Thanks,
Ian
Sorry if this is a double post - but my previous post seems to have vanished.
Use ViewGroup.onInterceptTouchEvent(MotionEvent)
You should Reference the Android Documentation as it's usage is quite complicated.
Basic Summary of use:
You receive the touch event here. If you want to consume it, return true and control will be passed to the ViewFlipper's onTouchEvent(). Return false and it will continue to be passed to the child. onTouchEvent() should also return true to ensure all further events are returned to the ViewFlipper's method. The child will also receive the original event with the action ACTION_CANCEL.
Finally It worked for me. Return true by default to get multiple calls on this listener.
viewFlipper.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (this.gestureDetector.onTouchEvent(event)) {
return false;
}
return true;
}
});
I was having the same problem and found your page trying to google for an answer.
After a few very frustrating attempts I ended up finding a quite easy solution, I'm still listening to the touch on the whole activity just like you did, but on the OnTouchEvent I filter if the ViewFlippers is touched or not:
#Override
public boolean onTouchEvent(MotionEvent event) {
if(mFlip.isInTouchMode()){
return gestureDetector.onTouchEvent(event);
} else{
return super.onTouchEvent(event);
}
}
hope it helps!