如何通过在ViewPager中用手指轻扫来禁用分页但仍然能够以编程方式轻扫?


549

我有ViewPager,在它下面有10个按钮。通过单击按钮(例如#4),寻呼机立即通过进入第4页mPager.setCurrentItem(3);。但是,我想通过水平滑动手指来禁用分页。因此,只能通过单击按钮来完成分页。那么,如何禁用手指滑动?


首先使用ViewFlipper怎么样?这将使您免于头痛。
Alex Semeniuk

Answers:


885

您需要子类化ViewPageronTouchEvent其中包含许多您不想更改的好东西,例如允许子视图得到触摸。 onInterceptTouchEvent是您要更改的内容。如果您查看的代码ViewPager,则会看到以下注释:

    /*
     * This method JUST determines whether we want to intercept the motion.
     * If we return true, onMotionEvent will be called and we do the actual
     * scrolling there.
     */

这是一个完整的解决方案:

首先,将此类添加到您的src文件夹:

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);
        setMyScroller();
    }

    public NonSwipeableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        setMyScroller();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // Never allow swiping to switch between pages
        return false;
    }

    //down one is added for smooth scrolling

    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*/);
        }
    }
}

接下来,确保使用此类而不是ViewPager您可能指定为的常规android.support.v4.view.ViewPager。在布局文件中,您需要使用类似以下内容的名称进行指定:

<com.yourcompany.NonSwipeableViewPager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

此特定示例位于中LinearLayout,旨在占据整个屏幕,这就是为什么layout_weight1和layout_height0dp的原因。

setMyScroller();方法是平稳过渡


3
@louielouie附带说明:有什么特殊原因,为什么您选择0dp身高/ 1体重解决方案而不是match_parent身高来实现全屏效果?这样是否可以提高性能?
ubuntudroid

28
使用键盘的向左/向右键(在模拟器中尝试)时,此答案不会阻止页面滑动。对于触摸设备来说可能不是问题,但对于电视和笔记本电脑来说可能就是一个问题。
Vincent Mimoun-Prat 2014年

8
@MarvinLabs @Thorbear通过键盘禁用页面滚动的正确方法是覆盖executeKeyEvent()。这是随后调用的方法allowScroll()// Never allow swiping by keyboard LEFT, RIGHT, TAB and SHIFT+TAB keys @Override public boolean executeKeyEvent(KeyEvent event) { return false; }
2015年

6
好吧,这也会禁用垂直滚动...如果使用列表视图,这是不好的。
maysi 2015年

5
我希望Google可以提供一种方法,为我们提供有关如何处理触摸/滑动的接口方法,因为我认为这不会造成伤害?
霓虹灯Warge

466

更一般的扩展ViewPager是创建一个SetPagingEnabled方法,以便我们可以即时启用和禁用分页。要启用/禁用刷卡,只需覆盖两种方法:onTouchEventonInterceptTouchEvent。如果禁用分页,则两者都将返回“ false”。

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

然后选择它而不是XML中的内置viewpager

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

您只需要使用调用该setPagingEnabled方法,false用户将无法滑动以进行分页。


3
非常适合具有多个子视图的视图,其中一个子视图使用水平滚动(例如,AChartEngine图表)。在我的片段中,我使用了一个回调到我的活动中,该回调告诉它是打开还是关闭分页,具体取决于用户是触摸(ACTION_MOVE)图表还是将其保留(ACTION_CANCEL)。非常感谢!
2014年

32
您可以简化onTouchEventonInterceptTouchEvent与方法return enabled && super.onTouchEvent(event);
nbarraille

2
@nbarraille只是样式问题。您可以使用任何看起来更易读的样式。
Rajul 2014年

7
我还建议将字段名称从“已启用”更改为“ swipePageChangeEnabled”或类似名称。编写代码一个月后,您几乎不记得“启用”的含义了,尤其是当您的类称为“ CustomViewPager”时,不清楚什么是自定义。这也是样式的问题,但是如果您不想以无法支持​​的项目结束,样式就很重要,完全重写比修复它容易。
bytefu'4

3
在哪里调用setPagingEnabled?._。
Ntikki 2015年

107

最简单的办法就是setOnTouchListener和回报trueViewPager

mPager.setOnTouchListener(new OnTouchListener()
    {           
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            return true;
        }
    });

53
有时不起作用。我正在使用带有FragmentPagerAdapter和几个Fragment的ViewPager。将OnTouchListener设置为寻呼机后,如果我向左跳,则UI仍将向左移动一点。
Chris.Zou

16
当您pager.setCurrentItem(pager.getCurrentItem());在返回之前添加时,它可以工作true
2013年

1
以前对我有用。不知道为什么它不能再正常工作了。
android开发人员

似乎为我工作。为了解决public int getItemPosition(Object object) { return POSITION_NONE; }我的适配器中存在的布局故障,这会迫使页面重新生成并可能还会解决其他问题。
r-hold

6
这是部分有效的解决方案。水平滑动会以某种奇怪的方式处理。我在ViewPager中使用Drag'n Drop Gridview对此进行了测试。使用此解决方案拖动时,从左向右拖动以及从右向左拖动都会失败。我个人认为Rajul的方法是最好的。
Ton Snoei 2014年

58

最好声明它为可样式化,因此可以从xml更改其属性:

private boolean swipeable;

public MyViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyViewPager);
    try {
        swipeable = a.getBoolean(R.styleable.MyViewPager_swipeable, true);
    } finally {
        a.recycle();
    }
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return swipeable ? super.onInterceptTouchEvent(event) : false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return swipeable ? super.onTouchEvent(event) : false;
}

并在您的values / attr.xml中:

<declare-styleable name="MyViewPager">
  <attr name="swipeable" format="boolean" />
</declare-styleable>

这样就可以在布局xml中使用它:

<mypackage.MyViewPager
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/viewPager"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:swipeable="false" />

当然,您仍然可以拥有一个get / set属性。


58

如果您将ViewPager本身放在另一个ViewPager中onTouchEventonInterceptTouchEvent则仅覆盖它是不够的。子ViewPager将从父ViewPager窃取水平滚动触摸事件,除非它位于其第一页/最后一页。

为了使此设置正常工作,您还需要覆盖该canScrollHorizontally方法。

请参阅LockableViewPager下面的实现。

public class LockableViewPager extends ViewPager {

    private boolean swipeLocked;

    public LockableViewPager(Context context) {
        super(context);
    }

    public LockableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public boolean getSwipeLocked() {
        return swipeLocked;
    }

    public void setSwipeLocked(boolean swipeLocked) {
        this.swipeLocked = swipeLocked;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return !swipeLocked && super.onTouchEvent(event);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return !swipeLocked && super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean canScrollHorizontally(int direction) {
        return !swipeLocked && super.canScrollHorizontally(direction);
    }

}

3
谢谢,这在另一个ViewPager内的ViewPager上效果很好。
Fernanda Bari

1
这适用于我,也适用于另一个ViewPager中的ViewPager。在这种情况下,正确的解决方案对我不起作用。
拉斐尔·鲁伊斯·穆尼奥斯

在选项卡中使用时也停止动画。
Rishabh Srivastava

如果我禁用了它并想启用它,那么在哪里可以使事件调用setSwipeLocked(false)?
拉维·亚达夫

57

现在我们无需创建自定义 ViewPager

ViewPager2 android中可用的新名称视图

垂直方向支撑

  • ViewPager2除了传统的水平寻呼外,还支持垂直寻呼。您可以ViewPager2通过设置元素的android:orientation属性来启用元素的垂直分页

使用XML

<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:orientation="vertical" />

使用代码

禁用正在viewpager2使用的刷卡

viewPager2.setUserInputEnabled(false);

viewpager2使用中启用刷卡

viewPager2.setUserInputEnabled(true);

有关更多信息,请检查此

更新


3
很好,但看起来仍然不完整。我用5个不同的片段进行了尝试,在页面之间切换后,片段中的一种丢失了,即视图既没有还原也没有重新膨胀
Toochka,

@Toochka很遗憾听到对我来说一切正常,您可以在这里找到示例工作代码stackoverflow.com/a/54643817/7666442如果可能,请分享您的代码
Nilesh Rathod

1
我可以使用此方法成功禁用ViewPager2上的滑动
voghDev

1
@voghDev很高兴听到这个消息
Nilesh Rathod

1
@PhaniRithvij请查看这个答案stackoverflow.com/a/54643817/7666442我加入了所有的细节如何使用viewpager2RecyclerView.Adapter
Nilesh制作Rathod

35

如果从ViewPager扩展,则还必须executeKeyEvent按照@araks先前的指示进行覆盖

@Override
public boolean executeKeyEvent(KeyEvent event)
{
    return isPagingEnabled ? super.executeKeyEvent(event) : false;
}

由于某些设备(例如Galaxy Tab 4 10')显示以下按钮,而大多数设备从不显示这些按钮:

键盘按键


50
三星一直在为Android开发人员搞砸。
toobsco42

2
@ toobsco42在这种情况下,三星并不孤单。SwiftKey(流行键盘应用程序)允许用户在其键盘上放置箭头。
苏菲安

1
如果您想阻止使用键盘/轨迹球的人寻呼您的寻呼机,这也可以解决。
se22as

28

禁用滑动

mViewPager.beginFakeDrag();

启用滑动

mViewPager.endFakeDrag();

22
这不是一个好的解决方案,因为它允许很小的移动量,至少在我的应用程序中。
koras

对我来说很好。与提供的其他解决方案相比,缺点是什么?
userM1433372

13

我需要禁用在一个特定页面上的滑动,并给它一个漂亮的橡皮筋动画,方法如下:

    mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageScrolled(int position, float positionOffset,
                                   int positionOffsetPixels) {
            if (position == MANDATORY_PAGE_LOCATION && positionOffset > 0.5) {
                mViewPager.setCurrentItem(MANDATORY_PAGE_LOCATION, true);
            }
        }

它等待直到部分可见下一页。下一页的代码onPageSelected将被执行。甚至下一页也会切换。因此,不需要此代码。
CoolMind

13

我知道发布此消息的时间过晚,但这是实现目标的小技巧;)

只需在viewpager 下面添加一个虚拟视图即可:

<android.support.v4.view.ViewPager
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

<RelativeLayout
     android:id="@+id/dummyView"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
</RelativeLayout>

然后添加OnClickListener到您的RelativeLayout

dummyView = (RelativeLayout) findViewById(R.id.dummyView);

dummyView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
         //Just leave this empty
    }
});

借助布局,布局和行为获得一些创意,您将学习找到一种方法来做绝对想像的事情:)

祝好运!


如果您不需要处理事件,可以使用setClickable代替,这是一种更简单的方法。setOnClickListeneronClick
混沌

这会不会也阻止viewpager中的触摸?
Android开发人员

是的,它会的。这是OP @androiddeveloper所需的预期行为
Dinuka Jay

@RickGrimesTheCoder我认为您不理解我的问题。我的意思是viewpager片段中的视图。他们还会触摸吗?
Android开发人员

不,它们不会,因为viewpager本身具有一个点击侦听器。这仅适用于片段中没有交互元素的实例。例如,一个欢迎ViewPager,它动态地更改其片段@androiddeveloper
Dinuka Jay

12

我写了一个CustomViewPager带有滑动控件的:

public class ScrollableViewPager extends ViewPager {
    private boolean canScroll = true;
    public ScrollableViewPager(Context context) {
        super(context);
    }
    public ScrollableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public void setCanScroll(boolean canScroll) {
        this.canScroll = canScroll;
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return canScroll && super.onTouchEvent(ev);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return canScroll && super.onInterceptTouchEvent(ev);
    }
}

相反,如果设置canScrolltrueViewPager则可以用手指轻扫false

我在项目中使用了它,直到现在为止效果很好。


1
如果我在ViewPager中有一个按钮并且想要单击该怎么办?此解决方案停止了单击viewpager下的所有内容
。.– aimiliano

6

我成功地使用了这堂课。需要重写executeKeyEvent以避免在某些设备中使用箭头或为了可访问性而滑动:

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class ViewPagerNoSwipe extends ViewPager {
    /**
     * Is swipe enabled
     */
    private boolean enabled;

    public ViewPagerNoSwipe(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.enabled = false; // By default swiping is disabled
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return this.enabled ? super.onTouchEvent(event) : false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return this.enabled ? super.onInterceptTouchEvent(event) : false;
    }

    @Override
    public boolean executeKeyEvent(KeyEvent event) {
        return this.enabled ? super.executeKeyEvent(event) : false;
    }

    public void setSwipeEnabled(boolean enabled) {
        this.enabled = enabled;
    }

}

并在xml中这样调用它:

<package.path.ViewPagerNoSwipe
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

有用。仅禁用滑动,并且启用了选项卡上的单击。AS警告该performClick()方法不会被覆盖。
CoolMind '18

5

在Kotlin中,我的解决方案结合了以上答案。

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

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onTouchEvent(ev) else false
    }

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return if (swipeEnabled) super.onInterceptTouchEvent(ev) else false
    }

    override fun executeKeyEvent(event: KeyEvent): Boolean {
        return if (swipeEnabled) super.executeKeyEvent(event) else false
    }
}

覆盖onInterceptTouchEvent()将阻止子视图接收输入。在大多数情况下,这不是预期的行为。
Alex Semeniuk

我能够与每个片段的子视图进行交互。不确定您指的是什么。
杰夫·帕吉特

5

在Kotlin中,我们可以通过创建一个继承自ViewPager类的自定义窗口小部件并添加用于控制滑动行为的标志值来解决此问题。

NoSwipePager.kt

class NoSwipePager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) {

    var pagingEnabled: Boolean = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onTouchEvent(event)
        } else false
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        return if (this.pagingEnabled) {
            super.onInterceptTouchEvent(event)
        } else false
    }
}

在xml中

<your.package.NoSwipePager
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/tab_layout" />

禁用以编程方式刷卡。如果kotlin-android-extensionsbuild.gradle中应用了plugin,则可以通过编写以下代码来禁用滑动。

view_pager.pagingEnabled = false

否则,我们可以使用以下代码禁用刷卡:

val viewPager : ViewPager = findViewById(R.id.view_pager)
viewPager.pagingEnabled = false

覆盖onInterceptTouchEvent()将阻止子视图接收输入。在大多数情况下,这不是预期的行为。
Alex Semeniuk

@AlexSemeniuk在执行此操作后,您是否发现任何问题?我已经启用了对回收者视图项进行刷卡的某些操作,并且工作正常。因此,在我的情况下,实现效果很好。
Sagar Chapagain

Sagar Chapagain:当然可以。我的每个页面都包含自定义视图,该视图以各种方式处理触摸(包括滚动,拖动,单击和长按)。不调用将super.onInterceptTouchEvent(event)导致这些视图不接收任何输入(这是onInterceptTouchEvent方法的书面用途)。
Alex Semeniuk

如果是这种情况,您应该使用子片段并维护backstack。
Sagar Chapagain

这与当前问题有什么关系?片段放置在某些容器(即Views)内,它们自己的布局包含Views。无论ViewPager中包含什么内容,我仍然要处理这样一个事实,即重写onInterceptTouchEvent()方法阻止它(内容)接收输入。
Alex Semeniuk


1

禁用特定页面(在此示例中为第2页)上的滑动的另一种简单解决方案:

int PAGE = 2;
viewPager.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
        if (viewPager.getCurrentItem() == PAGE) {
                viewPager.setCurrentItem(PAGE-1, false);
                viewPager.setCurrentItem(PAGE, false);
                return  true;
        }
        return false;
}

1
This worked for me

viewPager.setOnTouchListener(new View.OnTouchListener() {
                                         @Override
                                         public boolean onTouch(View v, MotionEvent event) {
                                             if (viewPager.getCurrentItem() == 0) {
                                                 viewPager.setCurrentItem(-1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 1) {
                                                 viewPager.setCurrentItem(1, false);
                                                 return true;
                                             }
                                             else if (viewPager.getCurrentItem() == 2) {
                                                 viewPager.setCurrentItem(2, false);
                                                 return true;
                                             }
                                             return true;
                                         }
                                     });

1

如果使用ImageViews和编写图像库,并ViewPager支持缩放和平移,请参见此处描述的简单解决方案:通过扩展Phimpme Android中的默认ViewPager (和Github示例-PhotoView)来实现可缩放的ImageView。此解决方案不能ViewPager单独使用。

public class CustomViewPager extends ViewPager {
    public CustomViewPager(Context context) {
        super(context);
    }

    public CustomViewPager(Context context, AttributeSet attrs)
    {
        super(context,attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        try {
            return super.onInterceptTouchEvent(event);
        } catch (IllegalArgumentException e) {
            return false;
        }
    }
}

0

如果您想在Xamarin中为Android实施相同的功能,则这里是C#的翻译

我选择将属性命名为“ ScrollEnabled ”。因为iOS仅使用exat相同的命名。因此,您在两个平台上的名称均相同,从而使开发人员更容易。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Support.V4.View;
using Android.Util;

namespace YourNameSpace.ViewPackage {

    // Need to disable swiping for ViewPager, if user performs Pre DSA and the dsa is not completed yet
    // http://stackoverflow.com/questions/9650265/how-do-disable-paging-by-swiping-with-finger-in-viewpager-but-still-be-able-to-s
    public class CustomViewPager: ViewPager {
        public bool ScrollEnabled;

        public CustomViewPager(Context context, IAttributeSet attrs) : base(context, attrs) {
            this.ScrollEnabled = true;
        }

        public override bool OnTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnTouchEvent(e);
            }
            return false;
        }

        public override bool OnInterceptTouchEvent(MotionEvent e) {
            if (this.ScrollEnabled) {
                return base.OnInterceptTouchEvent(e);
            }
            return false;
        }

        // For ViewPager inside another ViewPager
        public override bool CanScrollHorizontally(int direction) {
            return this.ScrollEnabled && base.CanScrollHorizontally(direction);
        }

        // Some devices like the Galaxy Tab 4 10' show swipe buttons where most devices never show them
        // So, you could still swipe through the ViewPager with your keyboard keys
        public override bool ExecuteKeyEvent(KeyEvent evt) {
            return this.ScrollEnabled ? base.ExecuteKeyEvent(evt) : false;
        }
    }
}

在.axml文件中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <YourNameSpace.ViewPackage.CustomViewPager
      android:id="@+id/pager"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@android:color/white"
      android:layout_alignParentTop="true" />
</LinearLayout>

0

以上代码均无法正常工作。

<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/pager"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent" />
                </HorizontalScrollView>

0

这是我的实现
,如果您想禁用滑动动画,则可以向左和向右使用swipeListener,但仍然希望通过手指滚动但没有动画

1-替代Viewpager方法onInterceptTouchEventonTouchEvent

2-创建自己的 GestureDetector

3-检测滑动手势并使用 setCurrentItem(item, false)

ViewPager

public class ViewPagerNoSwipe extends ViewPager {
    private final GestureDetector gestureDetector;
    private OnSwipeListener mOnSwipeListener;

    public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
        mOnSwipeListener = onSwipeListener;
    }

    public ViewPagerNoSwipe(@NonNull Context context) {
        super(context);
        gestureDetector = new GestureDetector(context, new GestureListener());

    }

    public ViewPagerNoSwipe(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(context, new GestureListener());


    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        gestureDetector.onTouchEvent(ev);
        return false;
    }

    public class GestureListener extends GestureDetector.SimpleOnGestureListener {

        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeRight();
                        } else {
                            if(mOnSwipeListener!=null)
                                mOnSwipeListener.onSwipeLeft();
                        }
                        result = true;
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeBottom();
                    } else {
                        if(mOnSwipeListener!=null)
                            mOnSwipeListener.onSwipeTop();
                    }
                    result = true;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result;
        }
    }

    public interface OnSwipeListener {

         void onSwipeRight();

        void onSwipeLeft();

        void onSwipeTop();

        void onSwipeBottom();
    }
}

设置ViewPager时,请设置swipeListener

postsPager.setOnSwipeListener(new ViewPagerNoSwipe.OnSwipeListener() {
            @Override
            public void onSwipeRight() {

              postsPager.setCurrentItem(postsPager.getCurrentItem() + 1,false);

            }

            @Override
            public void onSwipeLeft() {

            postsPager.setCurrentItem(postsPager.getCurrentItem() - 1, false);

            }
             ...
           }

0

我只是稍微定制了viewpager并轻松禁用了滑动。

public class CustomViewPager extends ViewPager {

private boolean swipeLocked;

public CustomViewPager(Context context) {
    super(context);
}

public CustomViewPager(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public boolean getSwipeLocked() {
    return swipeLocked;
}

public void setSwipeLocked(boolean swipeLocked) {
    this.swipeLocked = swipeLocked;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    return !swipeLocked && super.onTouchEvent(event);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    return !swipeLocked && super.onInterceptTouchEvent(event);
}

@Override
public boolean canScrollHorizontally(int direction) {
    return !swipeLocked && super.canScrollHorizontally(direction);
}
}

0

如果您使用的是ViewPager2,则只需使用:

viewpager.setUserInputEnabled(false);

文档

启用或禁用用户启动的滚动。这包括触摸输入(滚动和甩动手势)和辅助功能输入。尚不支持禁用键盘输入。禁用用户启动的滚动时,通过setCurrentItem进行程序化滚动仍然有效。默认情况下,启用用户启动的滚动。

感谢:https : //stackoverflow.com/a/61685871/9026710


-1
shareViewPager?.setOnTouchListener(object :View.OnTouchListener{
            override fun onTouch(v: View?, event: MotionEvent?): Boolean {
                for (PAGE in 0..shareViewPager.adapter!!.count){
                    if (shareViewPager.currentItem==PAGE){
                        shareViewPager.setCurrentItem(PAGE-1,false)
                        shareViewPager.setCurrentItem(PAGE,false)
                    }}
                return true
            }

        })
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.