是否可以禁用ViewPager上的滚动


Answers:


355

一个简单的解决方案是创建自己的ViewPager带有private boolean标记的子类isPagingEnabled。然后覆盖onTouchEventonInterceptTouchEvent方法。如果为isPagingEnabledtrue,则调用该super方法,否则为return

public class CustomViewPager extends ViewPager {

    private boolean isPagingEnabled = true;

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

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

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

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

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

然后在Layout.XML文件<com.android.support.V4.ViewPager>中用<com.yourpackage.CustomViewPager>标签替换所有标签。

此代码改编自此博客文章


2
很棒的解决方案,效果很好。如果您想像猴子一样停止滑动,可以使用@Override覆盖OnPageChangeListener。public void onPageScrollStateChanged(final int state){switch(state){case ViewPager.SCROLL_STATE_SETTLING:mPager.setPagingEnabled(false); 打破; 案例ViewPager.SCROLL_STATE_IDLE:mPager.setPagingEnabled(true); 打破; } // noop}
Informatic0re

13
PS:在XML中,使用<yourpkgname.CustomViewPager ...代替<com.android,support.v4.ViewPager ...
thecr0w 2012年

要添加另一个类似的解决方案,您可以使用名为“ JazzyViewPager”的库:github.com/jfeinstein10/JazzyViewPager,只需调用setPagingEnabled(boolean)
android开发人员,

只能停止向右滚动吗?我只能向左滚动
赛义夫·哈默德

例如,在使用游戏控制器或键盘时,仍然可以通过滚动页面中的元素(按钮等)来“滚动”。如何完全禁用它?我想这是另一种应该被拦截的事件……
David Ferrand

34

有一个简单的解决方法:

当您想禁用viewpager滚动时,请执行以下操作:

mViewPager.setOnTouchListener(new OnTouchListener() {

   public boolean onTouch(View arg0, MotionEvent arg1) {
      return true;
   }
}); 

而当您想重新启用它时:

mViewPager.setOnTouchListener(null);

这样就可以了。


46
差不多,但是不完全是。触地得分仍在发生,因此您可以通过多次滑动来移动页面。
Flynny75

@Akhil Sekharan在使用此答案时正好面对Flynny面临的问题..但幸运的是,不知道该错误突然消失了.. :)像魔术一样起作用!
僵尸2012年

您可以轻扫一下,因此仍然需要遍历布尔布尔onInterceptTouchEvent(MotionEvent事件){按照slatons答案骑车
Ryan Heitner

28

这是我对Slayton的回答的轻量型变体:

public class DeactivatableViewPager extends ViewPager {
    public DeactivatableViewPager(Context context) {
        super(context);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !isEnabled() || super.onTouchEvent(event);
    }

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

使用我的代码,您可以使用禁用分页setEnable()


覆盖onInterceptTouchEvent()将阻止子视图接收输入。在大多数情况下,这不是预期的行为。
Alex Semeniuk

19

我找到了一个简单的解决方案。

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();

这就是您使用的所有代码吗?这对我不起作用。
贾里德·伯罗斯

17
对我不起作用。仍然可以做很多小的滑动。
DYS 2015年

此代码不正确bcz它像悬挂视图一样滚动非常缓慢
Ghanshyam Nayma

运气可能会起作用。更新到ViewPager可以破解此黑客。
指针为空,

它仍然在一点一点地拖累(
。– ekashking

14

我建议另一种解决此问题的方法。这个想法是通过scrollView包裹viewPager,以便当该scrollView不可滚动时,您的viewPager也是不可滚动的。

这是我的XML布局:

        <HorizontalScrollView
            android:id="@+id/horizontalScrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true" >

            <android.support.v4.view.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" />

        </HorizontalScrollView>

无需代码。

对我来说很好。


1
在所有这些答案中,我觉得这很简单,效果很好!
SREE

好...但是当您将地图作为ViewPager中的片段之一时,那么...就出现了问题
ekashking


3

最适合我的解决方案是:

public class DeactivatedViewPager extends ViewPager {

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

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

    @Override
    public boolean canScrollHorizontally(int direction) {
        return false;
    }
}

此后,将通过触摸禁用滚动,然后您仍然可以使用setCurrentItem方法更改页面。


不知道为什么,但是根本行不通。滚动仍然发生。
里卡多A.19年

1
canScrollHorizontally()方法在当前情况下无效。滑动时甚至不会调用它。
Alex Semeniuk

3

这是Kotlin和androidX的答案

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager

class DeactivatedViewPager @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : ViewPager(context, attrs) {

    var isPagingEnabled = true

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return isPagingEnabled && super.onInterceptTouchEvent(ev)
    }
}

2

怎么样:
我使用了CustomViewPager
,接下来,重写了scrollTo方法
,当我进行许多小滑动时,我检查了运动,它不会滚动到其他页面。

public class CustomViewPager extends ViewPager {

    private boolean enabled;

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onTouchEvent(event);
        }

        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        if (this.enabled) {
            return super.onInterceptTouchEvent(event);
        }

        return false;
    }

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

    @Override
    public void scrollTo(int x, int y) {
       if(enabled) {
          super.scrollTo(x, y);
       }
    }
}

我遇到的问题是,viewpager仍在进行少量滑动,但是重写 View.scrollTo(int x, int y)为我解决了这个问题。 感谢
Palm

在某些情况下,它会导致一些奇怪的行为。就像空虚而只留下空白页“-”一样
里卡多


1

来自androidx的新类ViewPager2允许使用方法setUserInputEnabled(false)禁用滚动

private val pager: ViewPager2 by bindView(R.id.pager)

override fun onCreate(savedInstanceState: Bundle?) {
    pager.isUserInputEnabled = false
}

0

斯莱顿的答案很好。如果您想像猴子一样停止滑动,可以使用以下方法覆盖OnPageChangeListener

@Override public void onPageScrollStateChanged(final int state) { 
        switch (state) { 
            case ViewPager.SCROLL_STATE_SETTLING: 
                mPager.setPagingEnabled(false); 
                break; 
            case ViewPager.SCROLL_STATE_IDLE: 
                mPager.setPagingEnabled(true); 
                break; 
        } 
    }

所以你只能并排滑动


1
我没有找到任何ViewPager方法,例如setPagingEnabled(boolean value)
Rakesh Yadav

setPagingEnabled(boolean value)由您创建,因为没有此类方法可以覆盖。
Kharak

不清楚此setPagingEnabled()方法的作用。请提供完整的代码。
Alex Semeniuk

0
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.Scroller;
import java.lang.reflect.Field;

public class NonSwipeableViewPager extends ViewPager {

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

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

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    // stop swipe 
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    // stop switching pages
    return false;
}

private void setMyScroller() {
    try {
        Class<?> viewpager = ViewPager.class;
        Field scroller = viewpager.getDeclaredField("mScroller");
        scroller.setAccessible(true);
        scroller.set(this, new MyScroller(getContext()));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public class MyScroller extends Scroller {
    public MyScroller(Context context) {
        super(context, new DecelerateInterpolator());
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int 
duration) {
        super.startScroll(startX, startY, dx, dy, 350 /*1 secs*/);
    }
}
}

然后在Layout.XML文件中,将--com.android.support.V4.ViewPager ---标记替换为--- com.yourpackage.NonSwipeableViewPager ---标记。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.