在我的Android-App中,我有以下布局:
<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>
它看起来像这样:
http://i.stack.imgur.com/lzL5u.png
我的目标是:
现在的问题是,scrollview会占用所有事件,而且根本无法访问viewpager。
关于如何解决这个问题的任何想法?
答案 0 :(得分:4)
对于对此问题的答案感兴趣或有类似问题的任何人,以下是我如何解决它。
首先,一般方法是制作一个自定义视图,拦截某些触摸事件并将它们委托给正确的孩子。
在我的情况下,viewpager应截取水平手势,而viewpager 位于顶部的scrollview应该只获取垂直scroll-events。 对我来说,一个特殊的要求是,viewpager也应该只拦截特定范围内的触摸事件,即虚拟视口,这是一个孩子里面覆盖的滚动视图。
在自定义布局类中,必须与onTouchEvent()方法一起覆盖onInterceptTouchEvent()方法:
@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;
}
如您所见,我总是检查DOWN事件并将其保存在类成员中,一旦检测到移动,我会检查它是否在x方向上执行(对于viewpager)。在那时被截获。我的calculateDelegatesHitRectangle()方法在这种情况下只检查我是否在界限内,除了触摸事件我想要的地方。
在onTouch中,我只将截取的水平手势重新路由到我的viewpager,后者通过setter注入此自定义视图。为了获得正确的手势,我还需要重新路由截获的DOWN事件。
从我的活动代码中我只设置了调度目标和委托视图:
dispatchAwareLayout.setDispatchTargetView(mImageViewPager);
dispatchAwareLayout.setDelegateView(mDummyViewport);