Frage

In my Android-App I've the following layout:

<CustomRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

<android.support.v4.view.ViewPager
    android:id="@+id/image_viewpager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    />

<OverScrollBounceScrollView 
    android:id="@+id/scrollview"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    >

    <LinearLayout
        android:id="@+id/user_profile_scroll_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >

        <RelativeLayout
            android:id="@+id/dummy_viewport"
            android:layout_width="match_parent"
            android:layout_height="350dp"
            >

        </RelativeLayout>

        <LinearLayout
            android:id="@+id/scroll_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:background="@android:color/white"
            >

            ...some content

        </LinearLayout>
    </LinearLayout>
</OverScrollBounceScrollView>
</CustomRelativeLayout>

It looks about this:

http://i.stack.imgur.com/lzL5u.png

My goals are:

  1. When I do a scroll in Y-direction I want the scrollview to take over and scroll normally
  2. When I scroll in X-direction I want the viewpager under the scrollview to take over

The problem now is, that the scrollview takes all the events and the viewpager can't be reached at all.

Any ideas on how to solve this?

War es hilfreich?

Lösung

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);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top