【问题标题】:Is it possible to disable scrolling on a ViewPager是否可以禁用 ViewPager 上的滚动
【发布时间】:2011-10-18 21:32:17
【问题描述】:

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

有人有什么想法吗?

【问题讨论】:

标签: android android-viewpager


【解决方案1】:

一个简单的解决方案是创建您自己的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

【讨论】:

  • 很好的解决方案,工作正常。如果你想停止像猴子一样滑动,你可以用 @Override public void onPageScrollStateChanged(final int state) { switch (state) { case ViewPager.SCROLL_STATE_SETTLING: mPager.setPagingEnabled(false); 覆盖 OnPageChangeListener休息; case ViewPager.SCROLL_STATE_IDLE: mPager.setPagingEnabled(true);休息; } // noop }
  • PS:在 XML 中,使用
  • 要添加另一个类似的解决方案,您可以使用名为“JazzyViewPager”的库:github.com/jfeinstein10/JazzyViewPager,然后调用 setPagingEnabled(boolean)
  • 是否可以只停止向右滚动?我只能向左滚动
  • 在使用游戏控制器或键盘时,仍然可以通过聚焦页面中的元素(按钮等)来“滚动”。如何完全禁用它?我想这是另一种应该被拦截的事件......
【解决方案2】:

有一个简单的解决方法:

当你想禁用 viewpager 滚动时:

mViewPager.setOnTouchListener(new OnTouchListener() {

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

当你想重新启用它时:

mViewPager.setOnTouchListener(null);

这样就可以了。

【讨论】:

  • 差不多,但不完全。触地仍然会发生,因此您可以通过多次小滑动来移动页面。
  • @Akhil Sekharan 所面临的问题正是弗林尼在使用这个答案时所面临的问题。但幸运的是,不知道这个错误发生得有多突然...... :) 并且像魅力一样工作!!
  • 你可以做很多小滑动,所以你仍然需要过度 public boolean onInterceptTouchEvent(MotionEvent event) {按照 slatons 回答骑车
【解决方案3】:

这是我对 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() 将阻止子视图接收输入。在大多数情况下,这不是预期的行为。
【解决方案4】:

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

//disable swiping
mViewPager.beginFakeDrag();

//enable swiping
mViewPager.endFakeDrag();

【讨论】:

  • 这就是你使用的所有代码吗?这对我不起作用。
  • 对我不起作用。仍然可以做很多小滑动。
  • 这段代码不正确 bcz 它滚动得很慢,就像挂视图
  • 这可能很幸运。对 ViewPager 的更新可以打破这种黑客攻击。
  • 它还在拖,但一点一点地(.
【解决方案5】:

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

无需代码。

对我来说很好。

【讨论】:

  • 在所有这些答案中,我觉得这很简单,效果很好!!
  • 好的...但是当您将地图作为 ViewPager 中的片段之一时...这是一个问题
  • @ekashking 您可以将焦点移到片段上,因此滚动会影响您的地图。
  • 只有一个缺点,如果您在 viewpager 的片段中有另一个 view pager,那么该 viewpager 也不会滑动
【解决方案6】:

在我使用 ViewPager 2 alpha 2 的情况下,下面的 sn-p 可以工作

viewPager.isUserInputEnabled = false

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

更多viewpager2 1.0.0-alpha02变化参考这里

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

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

更多viewpager2#1.0.0-alpha04变化参考这里

【讨论】:

    【解决方案7】:

    禁用滑动

     mViewPager.beginFakeDrag();
    

    启用滑动

     mViewPager.endFakeDrag();
    

    【讨论】:

    • 滚动仍然可以,只是不再流畅。这基本上只是在没有解决问题的情况下恶化质量。
    • 重复答案
    【解决方案8】:

    最适合我的解决方案是:

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

    【讨论】:

    • 不知道为什么,但它根本不起作用。滚动仍然发生。
    • canScrollHorizontally() 方法在当前场景下无效。滑动发生时甚至不会调用它。
    【解决方案9】:

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

    【讨论】:

      【解决方案10】:

      这个怎么样:
      我用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);
             }
          }
      }
      

      【讨论】:

      • 我遇到的问题是查看器仍在进行小滑动,但覆盖 View.scrollTo(int x, int y) 为我解决了这个问题。 谢谢
      • 在某些情况下会导致一些奇怪的行为。就像去了虚无,只留下一个空白页'-'
      【解决方案11】:

      我创建了一个基于从 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

      【讨论】:

        【解决方案12】:
        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
            }
        }
        

        【讨论】:

          【解决方案13】:

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

          所以你只能并排滑动

          【讨论】:

          • 没有找到setPagingEnabled(boolean value)等ViewPager的方法
          • setPagingEnabled(boolean value) 将由您创建,因为没有这样的方法可以覆盖。
          • 不清楚这个setPagingEnabled() 方法的作用。请附上完整的代码。
          【解决方案14】:

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

          private val pager: ViewPager2 by bindView(R.id.pager)
          
          override fun onCreate(savedInstanceState: Bundle?) {
              pager.isUserInputEnabled = false
          }
          

          【讨论】:

            【解决方案15】:

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

              viewPager.beginFakeDrag();   
            

            【讨论】:

            • 另外两个解决方案提到了这一行。为什么你的更好?复制它们的实用程序是什么?
            猜你喜欢
            • 2021-05-09
            • 2012-01-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多