Considering the example from the below image,
I'm looking for a solution to pass the touch events from the canvas View to the Viewpager. This is necessary for applying the same amount of zoom on both views at the same time.
Here's the technical description of what's going on,
(Lets consider the view as A, B & C)
A. Parent View
B. View
C. View Pager
Before the dispatchTouchEvent() is called on the children (B & C), the A.dispatchTouchEvent() will first calls A.onInterceptTouchEvent() to see if the view group is interested in intercepting the event.
So if A.onTouchEvent() returns false, then it goes back up to B.onTouchEvent(). If that returns false then it goes back up to C.onTouchEvent() and the dispatching continues as usual.
And upon returning true,
ACTION_CANCEL will be dispatched to all the children.
All the subsequent gesture events (till ACTION_UP/ACTION_CANCEL) will be consumed by the event listeners (OnTouchListener.onTouch()) if defined, else the event handler A.onTouchEvent() at A’s level.
At this point I can pass the events from the parent to the child views but can't let the 2 child view B. & C handle the events together (applying same amount of zoom on both views).
Is there any way to pass the touch events from the parent view to a child one so that they can process the events simultaneously?
Here's my layout setup,
<RelativeLayout
android:id="@+id/layoutParent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFFFF">
<com.androidapp.NonSwipeableViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="@color/transparent" />
<com.androidapp.DrawingView
android:id="@+id/drawing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/transparent" />
</RelativeLayout>
If I'm not wrong, you want to process the same touch event both on the top and bottom view. According to Android touch architecture, you can't handle touch events from multiple views at the same time. Either you have to process it inside the onTouchEvent()
method or pass to the next view. You also need to wait till the top view finish processing the MotionEvent(
) and let the child view to handle.
Here's a possible solution using RxAndroid approach,
Inside your canvas view's MotionEvent()
,
@Override
public boolean onTouchEvent(MotionEvent event) {
// process all touch events (UP/DOWN/MOVE)
//send events as observable
RxBus.getInstance().sendMotionEvent(event);
return true;
}
This will observe the motion events and notify all observers.
Now, inside your viewpager's onResume()
subscribe for the motion events so that whenever a change is made from the canvas It'll immediately pass the events.
Subscription RxBus _rxBus = RxBus.getInstance();
subscription = _rxBus.getMotionEvent()
.subscribe(new Action1<MotionEvent>() {
@Override
public void call(MotionEvent event) {
// call the onTouchEvent of your widget e.g. ImageView and pass the received event
// this will apply the same touch event that was applied in the canvas
// .onTouchEvent(event) is important to override the onTouchEvent() of your widget that will use the touch event
imageView.onTouchEvent(event);
}
});
The RxBus class is given below,
public class RxBus {
private static RxBus instance;
private final PublishSubject<MotionEvent> motion_event = PublishSubject.create();
public static RxBus getInstance() {
if (instance == null) {
instance = new RxBus();
}
return instance;
}
public void sendMotionEvent(MotionEvent motionEvent) {
motion_event.onNext(motionEvent);
}
public Observable<MotionEvent> getMotionEvent() {
return motion_event;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With