Android开发经验谈Android开发程序人生

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

2018-10-09  本文已影响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了。。。

上一篇 下一篇

猜你喜欢

热点阅读