For anyone who is interested in an answer to this question or has similar issues, here is how I solved it.
First of all, the general approach is to make a custom view that intercepts certain touch events and delegates them to the correct childs.
In my case a viewpager should intercept the horizontal gestures and the scrollview that is laying on top of the viewpager should only get the vertical scroll-events. One special requirement for me was, that the viewpager should also intercept only touch-events within a certain bound, namely a dummy-viewport, which is a child inside the overlaying scrollview.
Within the custom layout class one has to override the onInterceptTouchEvent() method in conjunction with the onTouchEvent() method:
@Override
public boolean onInterceptTouchEvent ( MotionEvent event ) {
// 1.) remember DOWN event ALWAYS as this is important start for every gesture
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialX = event.getX();
mInitialY = event.getY();
mInitialDownEvent = MotionEvent.obtainNoHistory(event);
mIsDownEventDispatched = false;
break;
case MotionEvent.ACTION_MOVE:
final float x = event.getX();
final float y = event.getY();
final int yDiff = (int) Math.abs(y - mInitialY);
final int xDiff = (int) Math.abs(x - mInitialX);
calculateDelegatesHitRectangle();
if(xDiff > mTouchSlop && mDelegateBounds.contains((int)event.getX(), (int)event.getY())){
// 2.) if we scroll more in X-direction AND we are within the bounds of our delegatinView
// then INTERCEPT event here, so this views onTouch will be called
Log.d("hitrect", "HITRECT--- TOP: " + mDelegateBounds.top + " BOTTOM: " + mDelegateBounds.bottom);
return true;
}
break;
}
return super.onInterceptTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 3.) we receive ALL following event after X-Scroll has been intercepted
// but the DOWN event was handled by this view so we have to dispatch the remembered down event
// so the dispatch-target has a valid start for the scroll-gesture
if(!mIsDownEventDispatched){
mDispatchTargetView.dispatchTouchEvent(mInitialDownEvent);
mIsDownEventDispatched = true;
}
mDispatchTargetView.dispatchTouchEvent(event);
Log.d("touch", "ROOT: onTouchEvent after Intercept " + event.getActionMasked());
return true;
}
As you can see, I always check and save the DOWN-event in a class member and as soon as a movement is detected, I check if it is performed in x-direction (for the viewpager). Is intercepted in then. My calculateDelegatesHitRectangle() method in this case only checks if I'am within the bounds, where I wanna except the touch events.
In onTouch I only reroute the intercepted horizontal gesture to my viewpager, which is injected to this custom view via a setter. In order to have a correct gesture, I also need to reroute the intercepted DOWN event.
From my Activity code I just set the dispatch target and the delegate view:
dispatchAwareLayout.setDispatchTargetView(mImageViewPager);
dispatchAwareLayout.setDelegateView(mDummyViewport);