有没有可能在ViewPager上禁用滚动?

155

我有一个ViewPager,它实例化了一个View。 我想在搜索结果返回到视图时短暂地禁用viewpager和子按钮的滚动。 我已经调用了viewPager.setEnabled(false) ,但这并没有禁用它们。

有人有任何想法吗?


16个回答

379
一个简单的解决方案是创建自己的 ViewPager 子类,它有一个私有布尔标志 isPagingEnabled。然后覆盖 onTouchEventonInterceptTouchEvent 方法。如果isPagingEnabled为 true,调用 super 方法;否则直接返回。
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
很棒的解决方案,运行良好。如果你想停止像猴子一样滑动,你可以重写 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; } // noop } - Informatic0re
13
P.S:在XML中,请使用<yourpkgname.CustomViewPager...而不是<com.android.support.v4.ViewPager... - thecr0w
要添加另一个类似的解决方案,您可以使用名为“JazzyViewPager”的库:https://github.com/jfeinstein10/JazzyViewPager,并调用setPagingEnabled(boolean)函数。 - android developer
能否仅停止向右滚动?我只能向左滚动。 - Saif Hamed
警告:“方法'setPagingEnabled(boolean)'从未使用”。我是否需要这段代码,还是可以将其删除?如果我这样做,会有任何负面影响吗? - iBEK
显示剩余5条评论

37

这个问题有一个简单的解决方法:

当你想禁用viewpager滚动时:

mViewPager.setOnTouchListener(new OnTouchListener() {

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

如果您想重新启用它,那么:

mViewPager.setOnTouchListener(null);

那就可以搞定了。


52
几乎,但并不完全。仍然会发生触摸,所以您可以通过进行许多小的滑动来移动页面。 - Flynny75
@Akhil Sekharan 当使用这个答案时,遇到了和Flynny一样的问题.. 但幸运的是,不知道为什么那个错误突然就消失了.. :) 然后就像魔法一样正常工作了!! - Zombie
你可以进行许多小的滑动,因此仍然需要按照Slaton的答案进行覆盖。公共布尔值onInterceptTouchEvent(MotionEvent事件)。 - Ryan Heitner

29

这里是我对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

20

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

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();

这是你使用的全部代码吗?这对我不起作用。 - Jared Burrows
19
对我来说不起作用,但仍可以进行许多小的滑动操作。 - DYS
这段代码不太合适,因为它滚动得非常缓慢,就像挂起的视图一样。 - GS Nayma
这可能是靠运气实现的。更新ViewPager可能会破坏这个hack。 - Pointer Null
它仍然拖着,但是一点一点地(。) - ekashking

20

在我使用 ViewPager 2 alpha 2 的情况下,以下代码片段有效:

viewPager.isUserInputEnabled = false

能够禁用用户输入(setUserInputEnabled、isUserInputEnabled)

有关更多更改,请参见viewpager2 1.0.0-alpha02

此外,最新版本的 ViewPager 2 alpha 4 还进行了一些更改。

方向和 isUserScrollable 属性不再是 SavedState 的一部分。

有关更多更改,请参见viewpager2#1.0.0-alpha04


2
ViewPager2 的正确且可行的解决方案。 - issamux

17

我建议另一种解决这个问题的方法。思路是使用一个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
@ekashking 你可以将焦点移动到你的片段上,这样滚动就会影响你的地图。 - M. Marmor
只有一个缺点,如果在viewpager的一个fragment中有另一个viewpager,则该viewpager也无法进行滑动。 - kunal khedkar

5

禁用滑动

 mViewPager.beginFakeDrag();

启用滑动功能:
 mViewPager.endFakeDrag();

2
滚动仍然是可能的,只是不再流畅了。这基本上只是在恶化质量而没有解决问题。 - Benjamin Basmaci
1
重复的答案 - Ricardo A.

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)
    }
}

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方法来更改页面。


不知道为什么,但它就是不起作用。滚动仍然发生。 - Ricardo A.
1
“canScrollHorizontally()”方法在当前情况下没有效果。 当滑动发生时,它甚至都没有被调用。 - Alex Semeniuk

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
在某些情况下,它会导致一些奇怪的行为。比如进入虚空,只留下一个空白页面 '-'。 - Ricardo A.

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