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!
Related
I am working on android surface view with touch events.
Below is the code I wrote for surface view to handle touch events.
As shown in the image, I logged when the listener is called.
Then in when clause I handled ACTION_DOWN and ACTION_MOVE events.
However, when I touch the view, not only the when clause can't catch the event
but OnTouchListener is even not called too.
I also don't understand why trues in when clause are not used.
I wrote those expressions to tell OnTouchListener to return true.
Can anyone help me?
+) I figured out that my surfaceview doens't call onClick() too.
particleSurfaceView.setOnClickListener{ Log.d("sv", "click") }
never logs
Try making the touch listener always return true. If you ever return false, you stop getting notifications for that whole gesture / touch.
Well, it was Android Studio problem..
Touch event works but only the logging didn't work.
I have no idea why but after relaunching the Android Studio, it works.
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);
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.
I know that for an Android view, if I return true to onTouchEvent, then it means that you want to continue receiving events for the current gesture. If you return false it should not process more events for the current gesture
However I'd like to try to detect whether a gesture is a click or a hold/drag event, so I return true to the initial ACTION_DOWN event, until some number of milliseconds has elapsed, at which point I timeout and recognize the gesture as a hold/drag instead of a click.
Once the timeout has elapsed, I'd like to return false to further onTouchEvents, so that I can stop receiving events and let the parent view manage the rest of the drag.
However I seem to notice that once you return true for the first event, then it receives all further events with the associated gesture, even after I continually return false to later events. It seems the return value only matters for the very first event, after which it is ignored.
Is there any way to stop receiving onTouchEvent, and therefore pass it to the parent, once you have accepted the first event in a gesture?
Remember that the boolean return value of onTouchEvent only indicates whether the event has been handled or not - you should still receive events when the user is in the middle of a gesture.
Generally, you can tailor the behavior however you want in your handler:
private boolean hasHandledGesture = false;
public boolean onTouchEvent( MotionEvent event ){
if( !hasHandledGesture ){
// Do your actual handling here for the first event
return true;
} else {
return super.onTouchEvent( event );
}
}
However, I think in your case you'd be better off creating a handler that registers via setOnLongClickListener. Not only will it make your life easier, but you'll also let the OS decide how long it takes to make a long press. This is the best choice if you want to make the length of the press match the rest of the system, helping the overall app's native look and feel.
If you want to catch some more complex events, you might want to look at using a GestureDetector, but it probably is more complexity than you need if you're just detecting a long press.
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.