首页 > 其他 > 详细

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

时间:2021-04-13 23:29:40      阅读:30      评论:0      收藏:0      [点我收藏+]

在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 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();
                        int top = mViewGroup.getTop();
                        //获取父布局顶点的坐标
                        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);
                Log.e("TAG", "yhhhhhhhh");
                break;
            case MotionEvent.ACTION_MOVE:
                getParent().requestDisallowInterceptTouchEvent(true);
                if (mDownX >= 0
                        && mDownY >= mRootTopY
                        && mDownX <= mRootMeasuredWidth
                        && mDownY <= (mRootMeasuredHeight + mRootTopY)) {

                    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 : endX > maxX ? maxX : endX;
                    //Y轴边界限制
                    endY = endY < 0 ? 0 : endY > maxY ? maxY : endY;
                    //开始移动
                    setX(endX);
                    setY(endY);
                }

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

        super.onTouchEvent(event);

        return true;
    }


}

  

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

原文:https://www.cnblogs.com/jianglijs/p/14655056.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!