是否可以禁用 ViewPager 上的滚动

我有一个实例化 ViewViewPager。当搜索结果返回到视图时,我想暂时禁用视图页面滚动和子按钮。我已经呼叫 viewPager.setEnabled(false),但这不能禁用它。

有人知道吗?

136035 次浏览

一个简单的解决方案是创建自己的 ViewPager子类,它具有 private boolean标志 isPagingEnabled。然后重写 onTouchEventonInterceptTouchEvent方法。如果 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.yourpackage.CustomViewPager>标记替换任何 <com.android.support.V4.ViewPager>标记。

此代码改编自此 博客文章

斯莱顿的答案没问题。 如果你想停止像猴子一样滑动,你可以覆盖 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;
}
}

所以你只能并排滑动

对于这个问题,有一个简单的解决办法:

当你想禁用视图页面滚动时:

mViewPager.setOnTouchListener(new OnTouchListener() {


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

当你想重新启动它的时候:

mViewPager.setOnTouchListener(null);

这样就行了。

以下是我对斯莱顿答案的轻量级变体:

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()的分页。

我找到了一个简单的解决办法。

//disable swiping
mViewPager.beginFakeDrag();


//enable swiping
mViewPager.endFakeDrag();

这样吧:
我用的是 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);
}
}
}

禁止滑动

 mViewPager.beginFakeDrag();

使滑动启用滑动

 mViewPager.endFakeDrag();

对我来说最好的解决办法是:

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

我建议用另一种方法来解决这个问题。这个想法是用 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>

不需要代码。

我觉得挺好的。

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

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

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


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

在我使用 ViewPager 2alpha 2的情况下,下面的代码片段可以工作

viewPager.isUserInputEnabled = false

禁用用户输入的能力(setUserInputEnable,isUserInputEnable)

有关 Viewpager21.0.0-alpha02中的更多更改,请参考此文

最新版本 ViewPager 2 alpha 4也做了一些更改

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

有关 Viewpager2 # 1.0.0-alpha04中的更多更改,请参考此文

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

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

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