阅读更多         在Android里Touch是很常用的事件,尤其实在自定义控件中,要实现一些动态的效果,往往要对Touch进行处理。Android中主要有3个地方可以处理Touch事件:

        一、在View里,有两个回调函数

public boolean dispatchTouchEvent(MotionEvent ev);public boolean onTouchEvent(MotionEvent ev);


        二、在ViewGroup里,有三个回调函数
public boolean dispatchTouchEvent(MotionEvent ev);public boolean onInterceptTouchEvent(MotionEvent ev);public boolean onTouchEvent(MotionEvent ev);


        三、在Activity里,有两个回调函数
public boolean dispatchTouchEvent(MotionEvent ev);public boolean onTouchEvent(MotionEvent ev);



        在这三个不同的地方,它们对Touch事件的处理流程很相似,但也有不同的地方。
        在本节,就先研究View对Touch的处理过程。首先,Touch事件先到达dispatchTouchEvent(),我们来看看View.dispatchTouchEvent()的源码,这里面涉及到View的onTouchListener,和onTouchEvent()。


   
public boolean dispatchTouchEvent(MotionEvent event) {        if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onTouchEvent(event, 0);        }        if (onFilterTouchEventForSecurity(event)) {            //noinspection SimplifiableIfStatement            ListenerInfo li = mListenerInfo;            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED                    && li.mOnTouchListener.onTouch(this, event)) {                return true;            }            if (onTouchEvent(event)) {                return true;            }        }        if (mInputEventConsistencyVerifier != null) {            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);        }        return false;    }

        从源码中,我们可以看出View的onTouchListener和onTouchEvent都是在这里被调用的。如果View的touchListener返回true,dispatchTouchEvent()直接就返回,连onTouchEvent都不会被调用了。只有View没有设置onTouchListener,或者touchListener.onTouch()返回false,才会调用onTouchEvent()。
        我们还可以看出,如果onTouchEvent()被执行了的话,dispatchTouchEvent()的返回值就是onTouchEvent()的返回值。事实上,真正起作用的也就是dispatchTouchEvent(),onTouchEvent()只是被dispatchTouchEvent()调用了而已。关于这个返回值的作用,请往下看。

        我们需要一些实验,自定义控件还使用之前的画板

package com.ipjmc.vgdemo;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Paint;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;public class CustomView extends View {private static final String TAG = "CustomView";private int mLastX, mLastY;private int mCurrX, mCurrY;private Bitmap mBitmap;private Paint mPaint;public CustomView(Context context, AttributeSet attrs) {super(context, attrs);mPaint = new Paint();mPaint.setStrokeWidth(6);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);int width = getWidth();int height = getHeight();if (mBitmap == null) {mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);}Canvas tmpCanvas = new Canvas(mBitmap);tmpCanvas.drawLine(mLastX, mLastY, mCurrX, mCurrY, mPaint);canvas.drawBitmap(mBitmap, 0, 0, mPaint);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {Utils.log(TAG, "dispatchTouchEvent", event.getAction());return super.dispatchTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {mLastX = mCurrX;mLastY = mCurrY;mCurrX = (int) event.getX();mCurrY = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mLastX = mCurrX;mLastY = mCurrY;break;default:break;}invalidate();return true;}}

        我们在画板上画一条线,看一下日志



        如果我们把dispatchTouchEvent的返回值改为true,无论onTouchEvent()的返回值是什么,都不影响。

        现在,我们把dispatchTouchEvent的返回值,改为false看看会怎么样

@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {Utils.log(TAG, "dispatchTouchEvent", event.getAction());super.dispatchTouchEvent(event);return false;}

        我们在画板上画一条线,看一下日志


        我们可以看到,只在Touch事件是ACTION_DOWN的时候,打印了一条日志,而且画板上也没有画出一条线。这是说明在ACTION_DOWN的时候,如果dispatchTouchEvent返回false,那么这个View就接收不到后面的触屏事件了。
        如果我们这样改呢?dispatchTouchEvent()只在ACTION_DOWN的时候,返回true,其他时候返回false。答案是一切又恢复正常了。

public boolean dispatchTouchEvent(MotionEvent event) {Utils.log(TAG, "dispatchTouchEvent", event.getAction());super.dispatchTouchEvent(event);if (event.getAction() == MotionEvent.ACTION_DOWN) {return true;}return false;}

        可以这样理解。每一个触屏事件都必须是以ACTION_DOWN作为开头,后面跟一系列的ACTION_MOVE,最后再有一个ACTION_UP(或ACTION_CANCEL),标识触屏事件结束。所以Android就在ACTION_DOWN的时候做文章,官方文档对dispatchTouchEvent的返回值的解释是:True if the event was handled by the view, false otherwise。我们可以简单的理解为如果返回true,就说明它需要处理这个事件,就让它接收所有的触屏事件,否则,说明它不用处理,也就不让它接收后续的触屏事件了。
  • 大小: 62.7 KB
  • 大小: 9.7 KB
  • 查看图片附件

更多相关文章

  1. Android(安卓)设置DrawableRight和DrawableLeft 点击事件
  2. Android中的多击事件
  3. Broadcast
  4. SE for Android(安卓)系列之整体概要(三)
  5. Android(安卓)X库 BiometricPrompt 中 Crypto primitive not ini
  6. 史上最全面解析Android事件分发机制
  7. Android事件分发机制详解:史上最全面、最易懂
  8. android点击事件,第一次无效,第二次才响应的问题
  9. 关于android 双击事件

随机推荐

  1. 图表(APAndroidChart)
  2. Android通知Notification学习 及 无法通
  3. android > ListView -- SimpleAdapter
  4. android 判断当前application 是在前台还
  5. Android(安卓)Studio 3.0找不到Android(
  6. [zz] Android(安卓)Service 示例
  7. android 5.1 usb调试默认关闭设置方法
  8. Mainfest
  9. android设置全屏
  10. android 五种Log的意思