禁用ViewPager页面翻页的最佳方法

8
我正在开发一个应用程序,其菜单使用了ViewPager。每个fragment都有许多子视图,可能是ListViewScrollViewLinearLayout等等。其中一个fragment拥有一个设置按钮,可以切换一个带有ScrollView和一些LinearLayout(按钮)以及SeekBar的设置面板(LinearLayout包装器)。这个设置面板是通过上下滑动动画进行显示和隐藏,并且当它可见时我会禁用ViewPager的翻页功能。
@Override
public boolean onTouchEvent(MotionEvent event) {
    if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE) {
        return true;
    }
    return super.onTouchEvent(event);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE) {
        return true;
    }
    return super.onInterceptTouchEvent(event);
}

public boolean isPagingEnabled() {
    return pagingEnabled;
}

public void setPagingEnabled(boolean pagingEnabled) {
    this.pagingEnabled = pagingEnabled;
}

但是这也带来了一个问题,每次面板弹出时它的所有子视图都无法接收到OnTouchEvent事件,因此我添加了一个GestureDetector.SimpleOnGestureListener。
protected class YScrollDetector extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        Log.i(C.TAG, "distanceX " + distanceX + " distanceY " + distanceY);
        return Math.abs(distanceY) < Math.abs(distanceX);
    }
}

我将我的ViewPageronInterceptTouchEvent方法修改为:

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE && (mGestureDetector != null && mGestureDetector.onTouchEvent(event))) {
        return true;
    }
    return super.onInterceptTouchEvent(event);
}

这段代码可以运行,面板按钮可以接收它们的onClick,列表视图可以滑动等等...但这不是完美的,因为Math.abs(distanceY) < Math.abs(distanceX)不太准确。如果我快速上下或对角线滑动,或者用小幅滑动触摸按钮,onInterceptTouchEvent将返回true,因为mGestureDetector.onTouchEvent(event)也会返回true

经过一些谷歌搜索,我发现了这个:
viewPager.requestDisallowInterceptTouchEvent(true);

我尝试了类似于这样的东西:

myListView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        viewPager.requestDisallowInterceptTouchEvent(true);
        return false;
    }
});

它非常有效,因为在调用ViewPager.onInterceptTouchEvent时首先使用MotionEvent.ACTION_DOWN,然后立即调用myListView.setOnTouchListener并禁止其余的MotionEvent操作( MOVE和UP ),这样我就可以快速向上、向下、向两侧等滑动。 ViewPager不会翻页,但 ListView 滑动起来像个魅力。

但问题仍然存在,我必须向所有子视图onTouchEvent添加此requestDisallowInterceptTouchEvent(true),而且这不是优雅的代码。

所以我的问题是,我走对了吗?有没有办法避免将此侦听器添加到所有面板子视图(如果必须这样做,我会以最通用的方式去做)?

感谢您的时间。
2个回答

25

禁用翻页应该很简单,只需在onInterceptTouchEventonTouchEvent中都返回false即可。您不需要额外的手势检测来解决ViewPager问题。像这样扩展ViewPager

public class MyViewPager extends ViewPager {
    private boolean pagingEnabled = true;

    public MyViewPager(Context context) {
        super(context);
    }

    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setPagingEnabled(boolean pagingEnabled) {
        this.pagingEnabled = pagingEnabled;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return pagingEnabled && super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return pagingEnabled && super.onTouchEvent(event);
    }

}

我在我的一个应用程序中出于同样的原因使用了同样的东西(只是名称不同),它绝对有效。


1
我太蠢了,当然必须返回false eheh!如果我返回true,我将从孩子那里窃取运动事件,并且事件将无法通过onTouchEvent()分派到ViewGroup。谢谢! - GuilhE

1
你可以通过在viewpager上调用此方法来禁用分页

view_pager.setUserInputEnabled(false)

阅读更多


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接