150

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

有人有什么想法吗?

4

15 回答 15

378

一个简单的解决方案是创建您自己的ViewPager具有private boolean标志的子类,isPagingEnabled. 然后覆盖onTouchEventandonInterceptTouchEvent方法。如果isPagingEnabled等于 true,则调用该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>

此代码改编自此博客文章

于 2011-10-18T21:36:02.317 回答
36

有一个简单的解决方法:

当您想禁用 viewpager 滚动时:

mViewPager.setOnTouchListener(new OnTouchListener() {

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

当您想重新启用它时:

mViewPager.setOnTouchListener(null);

那会成功的。

于 2012-11-20T12:56:49.033 回答
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()

于 2014-09-01T08:29:30.793 回答
21

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

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();
于 2015-05-15T07:56:27.153 回答
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>

无需代码。

对我来说很好。

于 2017-04-05T08:35:59.640 回答
11

在我使用 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的更多更改,请参阅此内容

于 2019-12-21T10:34:45.033 回答
4

禁用滑动

 mViewPager.beginFakeDrag();

启用滑动

 mViewPager.endFakeDrag();
于 2017-03-01T06:37:35.603 回答
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方法来更改页面。

于 2017-03-09T05:25:02.960 回答
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)
    }
}
于 2019-01-17T10:12:42.720 回答
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);
       }
    }
}
于 2017-02-08T09:05:43.603 回答
2
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 --- 标签。

相同的解决方案,但在 Kotlin 中:

class NonSwipeableViewPager constructor(
    context: Context,
    attrs: AttributeSet?
) : ViewPager(context, attrs) {

    private var isPagingEnabled = true

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

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

    fun setPagingEnabled(isEnabled: Boolean) {
        isPagingEnabled = isEnabled
    }
}
于 2019-02-03T11:48:06.250 回答
2

我创建了一个基于从 Java 转换此答案的 Kotlin 版本:https ://stackoverflow.com/a/13437997/8023278

没有内置的方法来禁用 ViewPager 的页面之间的滑动,需要的是 ViewPager 的扩展,它覆盖 onTouchEvent 和 onInterceptTouchEvent 以防止滑动操作。为了使其更通用,我们可以添加一个方法 setSwipePagingEnabled 来启用/禁用页面之间的滑动。

class SwipeLockableViewPager(context: Context, attrs: AttributeSet): ViewPager(context, attrs) {
    private var swipeEnabled = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return when (swipeEnabled) {
            true -> super.onTouchEvent(event)
            false -> false
        }
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return when (swipeEnabled) {
            true -> super.onInterceptTouchEvent(event)
            false -> false
        }
    }

    fun setSwipePagingEnabled(swipeEnabled: Boolean) {
        this.swipeEnabled = swipeEnabled
    }
}

然后在我们的布局 xml 中,我们使用新的 SwipeLockableViewPager 而不是标准的 ViewPager

<mypackage.SwipeLockableViewPager 
        android:id="@+id/myViewPager" 
        android:layout_height="match_parent" 
        android:layout_width="match_parent" />

现在在我们的活动/片段中,我们可以调用myViewPager.setSwipePagingEnabled(false)并且用户将无法在页面之间滑动


更新

截至 2020 年,我们现在拥有ViewPager2。如果您迁移到 ViewPager2,则有一个内置方法可以禁用滑动:myViewPager2.isUserInputEnabled = false

于 2020-11-02T22:22:22.613 回答
0

slayton 的答案很好。如果你想停止像猴子一样滑动,你可以覆盖 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; 
        } 
    }

所以你只能并排滑动

于 2012-07-20T09:47:24.110 回答
0

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

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

override fun onCreate(savedInstanceState: Bundle?) {
    pager.isUserInputEnabled = false
}
于 2019-08-23T17:00:00.163 回答
-1

//禁用viewpager滚动的解决方案

  viewPager.beginFakeDrag();   
于 2021-09-27T08:31:53.680 回答