关于android 中ontouch和onclick的关系

onTouch方法监听了用户的按下点击等事件,自然包括了onclick的单机事件
若一个view同时设置了这两个监听就会出现一些事件冲突。

我的项目中有一个zoomIMageView,随手势滑动的放大缩小的imageview控件,之前直接网上下载的。现在我把zoomImageView放在了viewPager中,设置单机事件后,onclick就不响应了,查看zoomImageView后就发现已经有ontouch响应了事件,所以必须对源码进行一些修改才能符合我的需求。
先看zoomImagView的onTouch方法:

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        if (mGestureDetector.onTouchEvent(event))
            return true;
        mScaleGestureDetector.onTouchEvent(event);

        float x = 0, y = 0;
        // 拿到触摸点的个数
        final int pointerCount = event.getPointerCount();
        // 得到多个触摸点的x与y均值
        for (int i = 0; i < pointerCount; i++) {
            x += event.getX(i);
            y += event.getY(i);
        }
        x = x / pointerCount;
        y = y / pointerCount;

        /**
         * 每当触摸点发生变化时,重置mLasX , mLastY
         */
        if (pointerCount != lastPointerCount) {
            isCanDrag = false;
            mLastX = x;
            mLastY = y;
        }

        lastPointerCount = pointerCount;
        RectF rectF = getMatrixRectF();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:

            if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            break;
        case MotionEvent.ACTION_MOVE:

            if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            // Log.e(TAG, "ACTION_MOVE");
            float dx = x - mLastX;
            float dy = y - mLastY;

            if (!isCanDrag) {
                isCanDrag = isCanDrag(dx, dy);
            }
            if (isCanDrag) {//是否可以推动

                if (getDrawable() != null) {
                    if (getMatrixRectF().left == 0 && dx > 0) {
                        getParent().requestDisallowInterceptTouchEvent(false);
                    }

                    if (getMatrixRectF().right == getWidth() && dx < 0) {
                        getParent().requestDisallowInterceptTouchEvent(false);
                    }
                    isCheckLeftAndRight = isCheckTopAndBottom = true;
                    // 如果宽度小于屏幕宽度,则禁止左右移动
                    if (rectF.width() < getWidth()) {
                        dx = 0;
                        isCheckLeftAndRight = false;
                    }
                    // 如果高度小雨屏幕高度,则禁止上下移动
                    if (rectF.height() < getHeight()) {
                        dy = 0;
                        isCheckTopAndBottom = false;
                    }

                    mScaleMatrix.postTranslate(dx, dy);
                    checkMatrixBounds();
                    setImageMatrix(mScaleMatrix);
                }
            }
            mLastX = x;
            mLastY = y;
            break;

        case MotionEvent.ACTION_UP:

        case MotionEvent.ACTION_CANCEL:
            // Log.e(TAG, "ACTION_UP");
            lastPointerCount = 0;
            break;
        }

        return true;
    }

先测试return参数的作用是什么。这里不详解,直接写结果了。
1、return true消费了此次的触摸事件,其他事件将不再执行
2、return false 执行了ontouch方法,onclick事件也执行了,说明ontouch方法执行在onclick之前,这一点和onlongclick与onclick的关系是类似的

解决方案:在适当的时候让ontouch返回false
直接贴代码:

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int flag = 0;
        if (mGestureDetector.onTouchEvent(event))
            return true;
        mScaleGestureDetector.onTouchEvent(event);

        float x = 0, y = 0;
        // 拿到触摸点的个数
        final int pointerCount = event.getPointerCount();
        // 得到多个触摸点的x与y均值
        for (int i = 0; i < pointerCount; i++) {
            x += event.getX(i);
            y += event.getY(i);
        }
        x = x / pointerCount;
        y = y / pointerCount;

        /**
         * 每当触摸点发生变化时,重置mLasX , mLastY
         */
        if (pointerCount != lastPointerCount) {
            isCanDrag = false;
            mLastX = x;
            mLastY = y;
        }

        lastPointerCount = pointerCount;
        RectF rectF = getMatrixRectF();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            flag = 0;
            if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            break;
        case MotionEvent.ACTION_MOVE:
            flag = 1;
            if (rectF.width() > getWidth() || rectF.height() > getHeight()) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            // Log.e(TAG, "ACTION_MOVE");
            float dx = x - mLastX;
            float dy = y - mLastY;

            if (!isCanDrag) {
                isCanDrag = isCanDrag(dx, dy);
            }
            if (isCanDrag) {//是否可以推动

                if (getDrawable() != null) {
                    if (getMatrixRectF().left == 0 && dx > 0) {
                        getParent().requestDisallowInterceptTouchEvent(false);
                    }

                    if (getMatrixRectF().right == getWidth() && dx < 0) {
                        getParent().requestDisallowInterceptTouchEvent(false);
                    }
                    isCheckLeftAndRight = isCheckTopAndBottom = true;
                    // 如果宽度小于屏幕宽度,则禁止左右移动
                    if (rectF.width() < getWidth()) {
                        dx = 0;
                        isCheckLeftAndRight = false;
                    }
                    // 如果高度小雨屏幕高度,则禁止上下移动
                    if (rectF.height() < getHeight()) {
                        dy = 0;
                        isCheckTopAndBottom = false;
                    }

                    mScaleMatrix.postTranslate(dx, dy);
                    checkMatrixBounds();
                    setImageMatrix(mScaleMatrix);
                }
            }
            mLastX = x;
            mLastY = y;
            break;

        case MotionEvent.ACTION_UP:

        case MotionEvent.ACTION_CANCEL:
            // Log.e(TAG, "ACTION_UP");
            lastPointerCount = 0;
            break;
        }

        if (flag == 0) {
            return false;
        }
        return true;
    }

加了一个flag 判断是否是点击事件,如果是移动事件就返回true,不执行onclick方法,刚好也不会冲突。

使用时发现一些bug,zoomIMageView双手点击时也响应了单击事件,最后修改了放弃了家人flag方法。解决代码:
mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
if (isAutoScale == true) {
return true;
}

            float x = e.getX();
            float y = e.getY();
            // Log.e("DoubleTap", getScale() + " , " + initScale);
            if (getScale() < SCALE_MID) {
                ZoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MID, x, y), 16);
                isAutoScale = true;
            } else if (getScale() >= SCALE_MID && getScale() < SCALE_MAX) {
                ZoomImageView.this.postDelayed(new AutoScaleRunnable(SCALE_MAX, x, y), 16);
                isAutoScale = true;
            } else {
                ZoomImageView.this.postDelayed(new AutoScaleRunnable(initScale, x, y), 16);
                isAutoScale = true;
            }

            return true;
        }
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            siglelistener.onSingleClicked();
            return super.onSingleTapConfirmed(e);
        }
    });

onSingleTapConfirmed方法中回调给interface接口,自定义onclick给外部使用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值