美文网首页Android开发经验谈Android开发程序人生
全网最全解决ViewPager横向的ViewGroup滑动冲突的

全网最全解决ViewPager横向的ViewGroup滑动冲突的

作者: 为自己代颜_ | 来源:发表于2018-10-09 11:19 被阅读38次

    之所以说是全网最全是因为搜索了很多资料并没有一个很好的解决方案,只是解决部分的bug,在此做一下整理如下:
    首先项目中的需求界面结构是这样的我Fragment最外层使用的RecyclerView,然后RecyclerView列表中展示的各种各样的布局,实现效果图如下


    image.png

    底部有三个tab嵌套了三个fragment, fragment中又使用的RecyclerView实现列表数据展示。
    遇到的问题如下:

    1. 底部列表item显示不全,只能显示一平的item,原因是最外层是一个RecyclerView导致事件滑动冲突把事件消费掉了,使底部的RecyclerView无法拿到事件,无法滑动。
      解决方案:重写底部三个tab中嵌套的RecyclerView,重写onTouchEvent和dispatchTouchEvent目的是告诉父的RecyclerView我用事件的时候不要给我拦截,我用完之后你再拦截
      直接上代码:
    package com.tengniu.p2p.tnp2p.util.findfragment
    
    import android.content.Context
    import android.support.annotation.Nullable
    import android.view.MotionEvent
    import android.view.ViewConfiguration
    import android.support.v7.widget.RecyclerView
    import android.util.AttributeSet
    import android.util.Log
    
    
    /**
     * 作者:yshr on 2018/9/27 08:58
     * RecycelView嵌套RecycelView
     * 解决发现页面底部嵌套的RecycelView冲突的问题
     */
    
    class CustomRecyclerView : RecyclerView {
        private var mTouchSlop: Int = 0
    
        internal var move_x: Int = 0
        internal var move_y: Int = 0
        internal var x = 0f//初始化按下时坐标变量
        internal var y = 0f//初始化按下时坐标变量
    
        constructor(context: Context) : super(context) {
            val vc = ViewConfiguration.get(context)
            mTouchSlop = vc.scaledTouchSlop
        }
    
        constructor(context: Context, @Nullable attrs: AttributeSet) : super(context, attrs) {
            val vc = ViewConfiguration.get(context)
            mTouchSlop = vc.scaledTouchSlop
        }
    
        override fun onTouchEvent(e: MotionEvent): Boolean {
            Log.e("motion_event_mTouchSlop", mTouchSlop.toString())
            when (e.action) {
    
                MotionEvent.ACTION_DOWN -> {
                    move_x = e.x.toInt()
                    move_y = e.y.toInt()
                    parent.requestDisallowInterceptTouchEvent(true)
                    Log.e("motion_event", "down   x==y  $move_x ==== $move_y")
                }
                MotionEvent.ACTION_MOVE -> {
                    Log.e("motion_event", "move   x==y  $move_x ==== $move_y")
                    val y = e.y.toInt()
                    val x = e.x.toInt()
                    if (Math.abs(y - move_y) > mTouchSlop || Math.abs(x - move_x) < mTouchSlop * 2) {
                        parent.requestDisallowInterceptTouchEvent(false)
                    } else {
                        //告诉父控件不要拦截 子控件的操作
                        parent.requestDisallowInterceptTouchEvent(true)
                    }
                }
                MotionEvent.ACTION_UP -> {
                    performClick()
    //                parent.requestDisallowInterceptTouchEvent(true)
                    Log.e("motion_event", "up   x==y  $move_x ==== $move_y")
                }
            }
            return super.onTouchEvent(e)
        }
    
        override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
    
            parent?.requestDisallowInterceptTouchEvent(true);
            return super.dispatchTouchEvent(ev);
    
        }
    
    }
    
    

    注意点:也是容易进坑的点
    MotionEvent.ACTION_UP方法中一定要 加上performClick()方法,因为如果你不加的话,你会发现你列表中的item是没有点击事件的,即使是给设置监听并没有什么卵用
    因为自定义View中重写onTouchEvent后设置点击监听onClick()方法无效会引起冲突,冲突原因请查看参考这篇文章https://www.jianshu.com/p/7d1e773d9955
    OK了可以愉快的happy了。。。

    相关文章

      网友评论

      • l1zheng:楼主用CoordinatorLayout不是很容易实现这个布局吗,还不用考虑tab嵌套的recyclerView滑动冲突。而且tab还能悬浮
        为自己代颜_:@l1zheng :+1: 有时间研究下 多谢建议。。。

      本文标题:全网最全解决ViewPager横向的ViewGroup滑动冲突的

      本文链接:https://www.haomeiwen.com/subject/gcleaftx.html