I'm trying to figure out how to arrange my onInterceptTouchEvent
and onTouchEvent
overrides in various classes.
ButtonContainer
|
|-----------+
Button BitContainer
|
------------|
View1 View2
ButtonContainer and BitContainer are RelativeLayouts, Button, View1 and View2 are all imageviews with a drawable circle background. View1 and View2 are initially invisible.
The goal is to have ButtonContainer respond to the initial ACTION_DOWN
event by making view1 and view2 visible. On the ACTION_MOVE
event if the touch moves from Button over to View1, then the View1 onTouchEvent method should be called.
I thought I would be able to use onInterceptTouchEvent on ButtonContainer and set it to true in the case of ACTION_DOWN
but false in all other cases. Shouldn't this prevent the ACTION_MOVE
event from going straight to the ButtonContainer onTouch and make it traverse the tree instead? If so, then the ACTION_MOVE
event would follow the usual event flow and be detected by the other views, i.e View 1 & 2.
No matter what I do, I can't get the onTouchEvent methods in view1 or 2 to respond to the ACTION_MOVE gesture.
Is the event likely to be getting caught elsewhere? I noticed that if View 1 is visible and below the TouchEvent location on the ACTION_DOWN
even, it detects subsequent ACTION_MOVE
events... but if the TouchEvent occurs over view 2 or button, then view1 does not respond to ACTION_MOVE
.
EDIT: Ok, so I read a bit more and it seems that if an object 'doesnt consume the ACTION_DOWN event, then it won't consume any further events (for efficiency reasons)'...
I assume consume means 'is directly beneath' rather than 'is part of the ViewGroup'. Is that correct? Is there a way to pass the event to View1 so that it can be notified of ACTION_MOVE?
For anyone else facing this problem, the trick was to do the event dispatching manually.
Button1 returns true from the OnTouchEvent
if action = ACTION_DOWN.
When it is ACTION_MOVE
, then return false.
ButtonContainer returns true on onInterceptTouchEvent
when action is ACTION_MOVE
and then calls the dispatchTouchEvent
of BitContainer, which calls dispatchTouchEvent
on all t's child views using a for loop
From there, you can now write a method in each of your child views to check if the x position of the touchevent is within their own getLocationOnScreen()
coordinates.
Here is the onInterceptTouch event on ButtonContainer, and dispatchTouchEvent on BitContainer as an example:
Button Container
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
if (ev != null) {
if (ev.action == MotionEvent.ACTION_MOVE) {
bitContainer.dispatchTouchEvent(ev)
return true
}
}
return super.onInterceptTouchEvent(ev)
}
BitContainer
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
if (ev != null) {
if (ev.action == MotionEvent.ACTION_MOVE) {
for (i in 0 until this.getChildCount()) {
this.getChildAt(i).dispatchTouchEvent(ev)
}
}
}
return super.dispatchTouchEvent(ev)
}