• 解决在ScrollView中放入自定义可拖动的控件时,子控件滑动异常的问题


    在ScrollView中放入自定义可拖动的控件时,当拖动可拖动子控件时,MotionEvent先被根控件接收并依此传递给子控件,由于ScrollView是父控件,并他会检测事件是否滑动一段距离,所有当他使用事件时会造成可拖动控件拖动异常。

    解决该问题的好办法是在自定义控件中的onTouchEvent方法中在ACTION_DOWN,ACTION_MOVE调用requestDisallowInterceptTouchEvent(true)(如下),在ACTION_UP时调用requestDisallowInterceptTouchEvent(false)

    getParent().requestDisallowInterceptTouchEvent(true)

    上面代码的意思就是禁止父控件或者祖先控件拦截点击事件。


    参看文章
    https://www.jianshu.com/p/8c635cb59fdf
    https://www.jianshu.com/p/ff3b55441444
    /**
     * 可拖拽FrameLayout
     *
     * @author Jiangli
     * @see <a href="https://www.jianshu.com/p/19cd34e957e7">https://www.jianshu.com/p/19cd34e957e7</a>
     */
    public class DragFrameLayout extends FrameLayout {
    private static final String TAG = DragFrameLayout.class.getSimpleName();
    private float mDownX;
    private float mDownY;
    private int mRootTopY = 0;
    private int mRootMeasuredWidth = 0;
    private int mRootMeasuredHeight = 0;
    private int minTouchSlop;//系统可以辨别的最小滑动距离
    private boolean mHasMeasuredParent;//测量一次(如果父类动态改变,去掉此判断)

    private Context mContext;


    public DragFrameLayout(@NonNull Context context) {
    this(context, null);
    }

    public DragFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
    }

    public DragFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mContext = context;
    minTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    return super.dispatchTouchEvent(ev);
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    super.requestDisallowInterceptTouchEvent(disallowIntercept);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean interceptd = false;

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
    interceptd = false;
    //测量按下位置
    mDownX = event.getX();
    mDownY = event.getY();
    //测量父类的位置和宽高
    if (!mHasMeasuredParent) {
    ViewGroup mViewGroup = (ViewGroup) getParent();
    if (mViewGroup != null) {
    //获取父布局的高度
    mRootMeasuredHeight = mViewGroup.getMeasuredHeight();
    mRootMeasuredWidth = mViewGroup.getMeasuredWidth();
    //获取父布局顶点的坐标
    mRootTopY = mViewGroup.getTop();
    mHasMeasuredParent = true;
    }
    }

    break;

    case MotionEvent.ACTION_MOVE:
    //计算移动距离 判定是否滑动
    float dx = event.getX() - mDownX;
    float dy = event.getY() - mDownY;

    if (Math.abs(dx) > minTouchSlop || Math.abs(dy) > minTouchSlop) {
    interceptd = true;
    } else {
    interceptd = false;
    }

    break;

    case MotionEvent.ACTION_UP:
    interceptd = false;
    break;
    }

    return interceptd;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
    //解决parentView或者ancestorsView为ScrollView时,当前View不能自动滑动的问题
    getParent().requestDisallowInterceptTouchEvent(true);
    break;
    case MotionEvent.ACTION_MOVE:
    //Log.i(TAG, "ACTION_MOVE " + (mDownY >= mRootTopY) + (" mDownY = " + mDownY) + (" mRootTopY = " + mRootTopY));
    getParent().requestDisallowInterceptTouchEvent(true);
    if (mDownX >= 0
    && mDownX <= mRootMeasuredWidth
    && mDownY <= (mRootMeasuredHeight)) {
    float dx = event.getX() - mDownX;
    float dy = event.getY() - mDownY;

    float ownX = getX();
    //获取手指按下的距离与控件本身Y轴的距离
    float ownY = getY();
    //理论中X轴拖动的距离
    float endX = ownX + dx;
    //理论中Y轴拖动的距离
    float endY = ownY + dy;
    //X轴可以拖动的最大距离
    float maxX = mRootMeasuredWidth - getWidth();
    //Y轴可以拖动的最大距离
    float maxY = mRootMeasuredHeight - getHeight();
    //X轴边界限制
    endX = endX < 0 ? 0 : Math.min(endX, maxX);
    //Y轴边界限制
    endY = endY < 0 ? 0 : Math.min(endY, maxY);
    //开始移动
    setX(endX);
    setY(endY);
    }

    break;
    case MotionEvent.ACTION_UP:
    getParent().requestDisallowInterceptTouchEvent(false);
    break;
    }

    super.onTouchEvent(event);

    return true;
    }


    }

      

  • 相关阅读:
    解决linux下主机名变bogon的问题
    如何压缩虚拟机文件
    Linux shell crontab expdp 定时任务逻辑备份 定时删除旧文件
    .NET ramework 4.0安装失败
    Oracle数据库密码过期
    MySQL max_allowed_packet设置及问题
    WPF 异步执行
    win8 无法显示桌面,运行explorer.exe 提示 0xc0000018 异常 解决办法
    最全的Spark基础知识解答
    数据处理包plyr和dplyr包的整理
  • 原文地址:https://www.cnblogs.com/jianglijs/p/14655056.html
Copyright © 2020-2023  润新知