美文网首页
处理View滑动冲突

处理View滑动冲突

作者: 加油小李 | 来源:发表于2022-11-15 00:07 被阅读0次

内部拦截法和外部拦截法

外部拦截法

ViewGroup可以拦截掉Move事件但是不能拦截掉Down事件,因为View
还要相应Down事件
在自定义ViewGroup里面重写 onInterceptTouchEvent(MotionEvent ev)方法
并对Move的移动进行拦截。
import android.content.Context;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

import java.lang.reflect.Field;

public class MySwipeRefreshLayout extends SwipeRefreshLayout {
private static final String TAG = "MySwipeRefreshLayout";

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

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

private float startX;
private float startY;

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = ev.getX();
            startY = ev.getY();
           return false;
        case MotionEvent.ACTION_MOVE:
            float delX = Math.abs(ev.getX() - startX);
            float delY = Math.abs(ev.getY() - startY);
            //因为在move事件的时候,虽然子View设置了,getParent().requestDisallowInterceptTouchEvent(false);
            //但是往下滑动的时候我们发现在SwipeRefreshLayout的源码中报了以下错误
            //Got ACTION_MOVE event but don't have an active pointer id.
            //报这个错误的原因是因为 if (this.mActivePointerId == -1) 这个条件成立
            //所以我们需要想办法把这个属性改掉,由于SwipeRefreshLayout没有直接的API修改
            //因此我想到了反射把mActivePointerId属性改成0
            if ((delY - delX) > 0) {
                Class clazz = getClass().getSuperclass();

                Field field = null;
                try {
                    field = clazz.getDeclaredField("mActivePointerId");
                    field.setAccessible(true);
                    field.setInt(this, 0);
                    Log.e(TAG, "onInterceptTouchEvent: 反射成功");
                } catch (Exception e) {
                    Log.e(TAG, "onInterceptTouchEvent: 反射失败" + e.getMessage());
                    e.printStackTrace();
                }
            }

            break;

    }
    return super.onInterceptTouchEvent(ev);

}

}

内部拦截法

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

public class MyViewPager extends ViewPager {

private static final String TAG = "MyViewPager";


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

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

private float startX;
private float startY;

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(TAG, "子View: ACTION_DOWN");
            getParent(). requestDisallowInterceptTouchEvent(true);
            startX = ev.getX();
            startY = ev.getY();
            break;

        case MotionEvent.ACTION_MOVE:
            float delX = Math.abs(ev.getX() - startX);
            float delY = Math.abs(ev.getY() - startY);
            if (delX < delY) {
                Log.e(TAG, "子View: 取消禁用拦截");
                getParent().requestDisallowInterceptTouchEvent(false);
                return false;
            }

            break;
        case MotionEvent.ACTION_UP:
            Log.e(TAG, "子View: ACTION_UP");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(TAG, "子View: ACTION_CANCEL");
            break;
    }
    return super.dispatchTouchEvent(ev);
}

}

相关文章

网友评论

      本文标题:处理View滑动冲突

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