android viewpager 禁止滑动
- 前言
- 一、viewpager 禁止滑动是什么,有现成方法吗?
- 二、使用setOnTouchListener
- 三、使用自定义viewpager
- 总结
前言
本文介绍了本人有一个相关的需求需要实现这一功能,在过程中发现自己之前没做过,然后记录下实现这一功能的过程及相关的小知识点。
一、viewpager 禁止滑动是什么,有现成方法吗?
viewpager 禁止滑动,就是在特殊的条件,比如说编辑的状态下,是不允许用户滑动的,但是看了下viewpager 的源码,也百度了一下,并没有现成的API可以直接禁用调viewpager 的滑动,毕竟人家这个组件就是要滑动的,没有这个API也很正常。所以我们需要自己实现。
二、使用setOnTouchListener
自己实现嘛,一般来说就是能偷懒则偷懒的,先定义了一个isInterceptTouch的布尔值变量,在编辑态下设置为true,拦截事件。示例代码如下:
mBinding.viewPager.setOnTouchListener(object : View.OnTouchListener{
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
Log.d(TAG, "onTouch: $isInterceptTouch ${event?.action}")
return isInterceptTouch
}
})
调试过后发现还是能滑动,就是不流畅了,所以动了个小脑筋,在滑动的时候再把页面设置回来。划了一下没问题交给测试小伙伴了。代码现在是这个样子:
mBinding.viewPager.setOnTouchListener(object : View.OnTouchListener{
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
Log.d(TAG, "onTouch: $isInterceptTouch ${event?.action}")
if (isInterceptTouch){
mBinding.viewPager.setCurrentItem(mPos,false)
}
return isInterceptTouch
}
})
三、使用自定义viewpager
然后把,就不出意外的出意外了,测试反馈说我一点一点的滑动,还是可以话,我试了下确实是这样,但是日志又打印的确实是true,表示确实把事件已经拦截了,我一下子脑子卡主了,想了好一会才反应过来。顺便带大家复习一下setOnTouchListener和onTouchEvent的区别。
setOnTouchListener和onTouchEvent是Android中用于处理触摸事件的两种方法,它们有以下区别:
- 职责不同:onTouchEvent是View类中的一个方法,用于处理由View对象接收到的触摸事件。而setOnTouchListener则是View类的一个方法,它允许你为View对象设置一个OnTouchListener对象,这个对象可以响应View的触摸事件。
- 触发时机不同:当用户的触摸事件发生时,会最先由最内层的View对象(如按钮等)响应,如果该View对象没有消费该事件(即onTouch方法返回false),则会将事件传递给其父View对象,依此类推。如果最内层的View对象消费了该事件(即onTouch方法返回true),则该事件不会被传递给其父View对象。
- 处理方式不同:onTouchEvent是直接在View类中定义的方法,它的触发需要依赖传递过来的触摸事件信息。而setOnTouchListener则是为View对象设置了一个监听器,当用户的触摸事件发生时,会先由最内层的View对象响应,如果没有被消费,则会传递给其父View对象的onTouch方法;如果已经被消费,则不会传递给其父View对象的onTouch方法。
从复习结果上看当走到setOnTouchListener的时候,触摸事件其实已经被viewPager消费了,所以才会拦截不住,动歪脑筋设置setCurrentItem是没有用的。
因此,为了实现这一个需求,我不仅要自定义viewpager,使用onTouchEvent方法对触摸事件进行拦截,还要使用onInterceptTouchEvent防止其他子层级拿到消费事件。
再复习下onInterceptTouchEvent方法:这个方法主要存在于ViewGroup类中,用于拦截触摸事件。当返回值为false时,可以将点击事件传递到下层去;当返回值为true时,在这一层拦截点击事件,不能传递到下层去。
所以这个时候我的自定义viewpager就变成了这个样子
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import androidx.viewpager.widget.ViewPager
class NoScrollViewPager : ViewPager {
companion object {
private const val TAG = "NoScrollViewPager"
}
private var isScrollAllowed = true
constructor(context: Context?) : super(context!!) {}
constructor(context: Context?, attrs: AttributeSet?) : super(
context!!, attrs
) {
}
override fun onTouchEvent(event: MotionEvent): Boolean {
Log.d(TAG, "onTouchEvent: $isScrollAllowed")
return if (isScrollAllowed) {
super.onTouchEvent(event)
} else false
}
override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
Log.d(TAG, "onInterceptTouchEvent: $isScrollAllowed")
return if (isScrollAllowed) {
super.onInterceptTouchEvent(event)
} else false
}
fun setScrollAllowed(scrollAllowed: Boolean) {
isScrollAllowed = scrollAllowed
}
}
然后通过setScrollAllowed这个方法来控制是否禁止滑动ViewPager,这次没问题了。
总结
本文介绍了如何禁止Android中的ViewPager组件的滑动操作,由于ViewPager本就是为了滑动而设计的,因此并没有现成的API可以直接实现禁止滑动。通过自定义ViewPager并重写onTouchEvent和onInterceptTouchEvent方法,可以实现滑动拦截并禁止ViewPager的滑动操作。同时也介绍了setOnTouchListener和onTouchEvent的区别。