android viewpager 禁止滑动

04-27 872阅读

android viewpager 禁止滑动

  • 前言
  • 一、viewpager 禁止滑动是什么,有现成方法吗?
  • 二、使用setOnTouchListener
  • 三、使用自定义viewpager
  • 总结

    android 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中用于处理触摸事件的两种方法,它们有以下区别:

    1. 职责不同:onTouchEvent是View类中的一个方法,用于处理由View对象接收到的触摸事件。而setOnTouchListener则是View类的一个方法,它允许你为View对象设置一个OnTouchListener对象,这个对象可以响应View的触摸事件。
    2. 触发时机不同:当用户的触摸事件发生时,会最先由最内层的View对象(如按钮等)响应,如果该View对象没有消费该事件(即onTouch方法返回false),则会将事件传递给其父View对象,依此类推。如果最内层的View对象消费了该事件(即onTouch方法返回true),则该事件不会被传递给其父View对象。
    3. 处理方式不同: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的区别。

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]