嵌套Android ViewPager,水平滑动ListView中的ListItems

嵌套Android ViewPager,水平滑动ListView中的ListItems,android,listview,nested,android-viewpager,Android,Listview,Nested,Android Viewpager,我在活动的根级别上有一个ViewPager 寻呼机的每一页都包含一个ListFragment(由FragmentPagerAdapter支持) 一些列表视图项应该包含额外的ViewPager,以支持浏览这些项的内容(例如,列表项中的水平图库) 如何嵌套查看寻呼机?ViewPager->ListView(在页面中)->ViewPager(在列表项中) 我可以在列表片段之间水平滑动,也可以垂直滑动整个列表,但我不能在列表项内部滑动。您不能真正嵌套需要相同手势来控制它们的元素。因为视图寻呼机已经捕获了

我在活动的根级别上有一个ViewPager

寻呼机的每一页都包含一个ListFragment(由FragmentPagerAdapter支持)

一些列表视图项应该包含额外的ViewPager,以支持浏览这些项的内容(例如,列表项中的水平图库)

如何嵌套查看寻呼机?ViewPager->ListView(在页面中)->ViewPager(在列表项中)


我可以在列表片段之间水平滑动,也可以垂直滑动整个列表,但我不能在列表项内部滑动。

您不能真正嵌套需要相同手势来控制它们的元素。因为视图寻呼机已经捕获了水平运动,所以嵌套元素将无法获取它。通过管理focus等,你可能需要做很多工作来解决这个问题,但最终你的应用程序会让用户感到困惑。最好不要嵌套使用相同交互的元素。。。在这种情况下,两个视图寻呼机都在观察侧向运动。

虽然这不是最好的交互设计,但可以通过覆盖根级别活动的dispatchTouchEvent(MotionEvent ev)方法并使用RequestDisallowWinterCeptTouchEvent(true)来实现这一点在mainPager和当前ListView上,以防止其他滚动。看看这个例子:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {

    Fragment listFragment = getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + R.id.pager + ":" + (mainPager.getCurrentItem()));
    mainPager.getChildAt(mainPager.getCurrentItem());
    if (listFragment == null)
        return super.dispatchTouchEvent(ev);
    ViewPager embeddedPager = (ViewPager) listFragment.getView().findViewById(R.id.videopager);
    if (embeddedPager != null) {
        int[] position = new int[2];
        embeddedPager.getLocationOnScreen(position);
        if (ev.getY() > position[1] && ev.getY() < position[1] + embeddedPager.getHeight()) {
            mainPager.requestDisallowInterceptTouchEvent(true);
            if (embeddedPager.getScrollX() % embeddedPager.getWidth() != 0) {
                ListView listView = (ListView) listFragment.getView().findViewById(
                        android.R.id.list);
                listView.requestDisallowInterceptTouchEvent(true);
            }
        }
    }

    return super.dispatchTouchEvent(ev);
}
@覆盖
公共布尔dispatchTouchEvent(MotionEvent ev){
Fragment listFragment=getSupportFragmentManager().findFragmentByTag(
android:switcher:“+R.id.pager+”:“+(mainPager.getCurrentItem());
mainPager.getChildAt(mainPager.getCurrentItem());
如果(listFragment==null)
返回超级dispatchTouchEvent(ev);
ViewPager embeddedPager=(ViewPager)listFragment.getView().findViewById(R.id.videopager);
if(embeddedPager!=null){
int[]位置=新int[2];
嵌入式寻呼机。getLocationOnScreen(位置);
if(ev.getY()>position[1]&&ev.getY()
我在内部
ViewPager
中添加了一个
ontouch监听器

private OnTouchListener mSuppressInterceptListener = new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(
                event.getAction() == MotionEvent.ACTION_DOWN &&
                v instanceof ViewGroup
        ) {
                ((ViewGroup) v).requestDisallowInterceptTouchEvent(true);
        }
        return false;
    }
};
这只会检测内部
ViewPager
上的操作下触事件,并防止外部的操作下触事件拦截它。因为它返回false,所以只应命中ACTION_DOWN事件;所有其他事件都将被忽略。您可以将此侦听器添加到您想要“保护”的每个元素中,使其免受外部
ViewPager
滚动的影响,但显然,如果您想要在这些元素上拾取任何其他触摸行为,您需要在触摸侦听器中处理它们,并可能实现更好的侦听器


首先感谢@Rodja给了我这个想法。

谢谢你——我稍微修改了这个想法,让你把代码放在
活动之外的其他地方#dispatchTouchEvent(MotionEvent)
功能,但我使用的想法基本上是你的:)哇。干净多了。谢谢到目前为止,这是最简单的解决方案。简直不敢相信它有多容易工作。非常感谢,安德鲁和罗贾!我面临着类似的问题,这让我可以左右滑动。如果我还想启用点击,然后打开所选视图,该怎么办?您可以编写自己的点击监听器,方法是先听ACTION_DOWN,然后听ACTION_UP;如果两者之间的所有动作和移动事件的总和小于系统触摸斜率(见下文),则称之为单击。具有触摸斜率、长按和一般任何您需要的常数。