SwipeRefreshLayout + ViewPager,仅限制水平滚动?

use*_*501 89 android gesture android-viewpager swiperefreshlayout

我实现了SwipeRefreshLayoutViewPager我的应用程序,但有一个大麻烦:每当我要去刷卡左/右滚动页面之间切换过于敏感.稍微向下滑动也会触发SwipeRefreshLayout刷新.

我想设置水平滑动开始时的限制,然后强制水平直到滑动结束.换句话说,当手指水平移动时,我想取消垂直滑动.

这个问题只发生在ViewPager,如果我向下滑动并SwipeRefreshLayout触发刷新功能(显示条形图)然后我水平移动手指,它仍然只允许垂直滑动.

我试图扩展ViewPager课程,但它根本不起作用:

public class CustomViewPager extends ViewPager {

    public CustomViewPager(Context ctx, AttributeSet attrs) {
        super(ctx, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean in = super.onInterceptTouchEvent(ev);
        if (in) {
            getParent().requestDisallowInterceptTouchEvent(true);
            this.requestDisallowInterceptTouchEvent(true);
        }
        return false;
    }

}
Run Code Online (Sandbox Code Playgroud)

布局xml:

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/viewTopic"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.myapp.listloader.foundation.CustomViewPager
        android:id="@+id/topicViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激,谢谢

小智 146

我不确定你是否还有这个问题但是Google I/O app iosched解决了这个问题:

    viewPager.addOnPageChangeListener( new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled( int position, float v, int i1 ) {
        }

        @Override
        public void onPageSelected( int position ) {
        }

        @Override
        public void onPageScrollStateChanged( int state ) {
            enableDisableSwipeRefresh( state == ViewPager.SCROLL_STATE_IDLE );
        }
    } );


private void enableDisableSwipeRefresh(boolean enable) {
    if (swipeContainer != null) {
            swipeContainer.setEnabled(enable);
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用了相同的,并且工作得很好.

编辑:使用addOnPageChangeListener()而不是setOnPageChangeListener().

  • 完美地工作,但现在折旧setOnPageChangeListener.请改用addOnPageChangeListener. (5认同)
  • 最好的答案,但是将代码发布到enableDisableSwipeRefresh可能会很好(是的,从功能名称来看很明显..但是要确保我必须谷歌...) (4认同)
  • 这是最佳答案,因为它考虑了ViewPager的状态.它不会阻止源自ViewPager的向下拖动,这显然表明了刷新的意图. (3认同)
  • 链接到Google i/o应用中"enableDisableSwipeRefresh"的源代码:https://android.googlesource.com/platform/external/iosched/+/HEAD/android/src/main/java/com/google/samples /apps/iosched/ui/BaseActivity.java#1486 (2认同)

use*_*501 34

解决非常简单,没有任何扩展

mPager.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mLayout.setEnabled(false);
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                mLayout.setEnabled(true);
                break;
        }
        return false;
    }
});
Run Code Online (Sandbox Code Playgroud)

像魅力一样工作

  • viewPager.setOnTouchListener { _, event -&gt; swipeRefreshLayout.isEnabled = event.action == MotionEvent.ACTION_UP false } (2认同)

huu*_*duy 22

我遇到了你的问题.自定义SwipeRefreshLayout可以解决问题.

public class CustomSwipeToRefresh extends SwipeRefreshLayout {

private int mTouchSlop;
private float mPrevX;

public CustomSwipeToRefresh(Context context, AttributeSet attrs) {
    super(context, attrs);

    mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mPrevX = MotionEvent.obtain(event).getX();
            break;

        case MotionEvent.ACTION_MOVE:
            final float eventX = event.getX();
            float xDiff = Math.abs(eventX - mPrevX);

            if (xDiff > mTouchSlop) {
                return false;
            }
    }

    return super.onInterceptTouchEvent(event);
}
Run Code Online (Sandbox Code Playgroud)

请参阅ref:链接


小智 10

我根据之前的答案做了这个,但发现这样做有点好.该动作以ACTION_MOVE事件开始,根据我的经验以ACTION_UP或ACTION_CANCEL结束.

mViewPager.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                mSwipeRefreshLayout.setEnabled(false);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mSwipeRefreshLayout.setEnabled(true);
                break;
        }
        return false;
    }
});
Run Code Online (Sandbox Code Playgroud)


cor*_*992 9

由于某些原因,只有他们才知道,支持库开发人员团队认为适合强行拦截来自SwipeRefreshLayout子布局的所有垂直拖动动作事件,即使孩子专门请求事件的所有权.他们唯一检查的是它的主要子项的垂直滚动状态为零(在它的子项可垂直滚动的情况下).该requestDisallowInterceptTouchEvent()方法已被覆盖了一个空体,并且(不是那样)照亮了注释"Nope".

解决此问题的最简单方法是将类从支持库复制到项目中并删除方法覆盖.ViewGroup的实现使用内部状态进行处理onInterceptTouchEvent(),因此您不能再简单地重写该方法并复制它.如果您真的想要覆盖支持库实现,那么您必须在调用时设置自定义标志requestDisallowInterceptTouchEvent(),并根据该行为覆盖onInterceptTouchEvent()onTouchEvent()(或可能破解canChildScrollUp())行为.