我正试图用ViewPager使用SlidingPaneLayout,就这样
<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/scientific_graph_slidingPaneLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- The first child view becomes the left pane. --> <ListView android:id="@+id/left_pane" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="left" /> <!-- The second child becomes the right (content) pane. --> <android.support.v4.view.ViewPager android:id="@+id/scientific_graph_viewPager" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> </android.support.v4.widget.SlidingPaneLayout>
当我从左边缘拉出时,SlidingPaneLayout滑动;然而,当我从右边缘拉出来时,似乎无法让ViewPager滑动.当我从右边缘拉出时,它滑动得很少,然后弹回.
这样做是否可行?有没有更好的方法来做到这一点?
我发现通过将手指向上移动到左边,我可以滑动视图寻呼机.
解决方法
根本原因是#onInterceptTouchEvent的实现.一个较旧的SlidingPaneLayout实现调用#canScroll,它将检查触摸目标是否可以滚动,如果是,则滚动触摸目标,而不是滑动面板.除了在X拖动超过坡度并且Y拖动超过X拖动(如OP所指出)的情况下,拖动阈值超过坡度时,最近的实施看起来总是拦截运动事件.
一个解决方案是复制SlidingPaneLayout并进行一些更改以使其正常工作.这些变化是:
>修改#onInterceptTouchEvent中的ACTION_MOVE大小写,同时检查#canScroll,
if (adx > slop && ady > adx || canScroll(this,false,Math.round(x - mInitialMotionX),Math.round(x),Math.round(y))) { ... }
>将#canScroll的最终检查修改为特殊情况ViewPager.此更改也可以通过覆盖#canScroll在子类中完成,因为它不会访问任何私有状态.
protected boolean canScroll(View v,boolean checkV,int dx,int x,int y) { ... /* special case ViewPagers,which don't properly implement the scrolling interface */ return checkV && (ViewCompat.canScrollHorizontally(v,-dx) || ((v instanceof ViewPager) && canViewPagerScrollHorizontally((ViewPager) v,-dx))) } boolean canViewPagerScrollHorizontally(ViewPager p,int dx) { return !(dx < 0 && p.getCurrentItem() <= 0 || 0 < dx && p.getAdapter().getCount() - 1 <= p.getCurrentItem()); }
通过修复ViewDragHelper可能会有一个更优雅的方式,但这在未来的更新支持包中应该是Google应该解决的.上面的黑客现在应该使用ViewPagers(和其他水平滚动容器?)进行布局.