是否可以禁用ViewPager上的滚动

时间:2011-10-18 21:32:18

标签: android android-viewpager

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

有人有任何想法吗?

15 个答案:

答案 0 :(得分:336)

一个简单的解决方案是创建自己的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.android.support.V4.ViewPager>代码替换为<com.yourpackage.CustomViewPager>个代码。

此代码改编自此blog post

答案 1 :(得分:33)

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

如果要禁用viewpager滚动,请执行以下操作:

mViewPager.setOnTouchListener(new OnTouchListener() {

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

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

mViewPager.setOnTouchListener(null);

这样就可以了。

答案 2 :(得分: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()停用分页。

答案 3 :(得分:19)

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

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();

答案 4 :(得分:8)

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

无需代码。

对我来说很好。

答案 5 :(得分:5)

禁用滑动

 mViewPager.beginFakeDrag();

启用滑动

 mViewPager.endFakeDrag();

答案 6 :(得分:4)

对我有用的最佳解决方案是:

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

答案 7 :(得分: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);
       }
    }
}

答案 8 :(得分:2)

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

答案 9 :(得分:1)

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

所以你只能并排滑动

答案 10 :(得分:1)

当您使用上面的答案时,您可能会遇到一个错误的问题:“将isScrollEnabled设置为false,此viewPager中的某些视图无法处理onClick和onTouchEvent。因此,我给出解决方案,希望它可以为您提供帮助...

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

    var isScrollEnabled = true

    override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
        if(isScrollEnabled){ 
             super.onInterceptTouchEvent(event) 
         }else{
            return isScrollEnabled && super.onInterceptTouchEvent(event)
         }
    }
    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if(isScrollEnabled){
             return isScrollEnabled
         }else{
             return isScrollEnabled  && super.onTouchEvent(event)
        }
    }
}

答案 11 :(得分:1)

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

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

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

答案 12 :(得分: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 ---标记的标签。

答案 13 :(得分:0)

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

viewPager.isUserInputEnabled = false

  

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

请参阅此以获取viewpager2 1.0.0-alpha02

中的更多更改

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

  

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

请参阅此以获取viewpager2#1.0.0-alpha04

中的更多更改

答案 14 :(得分:0)

我基于从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。如果您migrate到ViewPager2,则有一个内置的方法来禁止滑动:myViewPager2.isUserInputEnabled = false