阅读更多         在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 事件处理(三)
  2. 【Android】ListView与Button的共存问题解决
  3. View事件分发机制
  4. Android使用返回键退出实现
  5. android中的UI控制(二)
  6. android中的UI控制(二)
  7. Android事件分发机制
  8. iphone开发之常用控件的使用详解
  9. Android(安卓)Keyboard/Touch Panel分析

随机推荐

  1. Sql Server触发器的使用
  2. jdbc连接sql server数据库问题分析
  3. SQL Server高可用的常见问题分析
  4. sql处理数据库锁的存储过程分享
  5. SQLSERVER 本地查询更新操作远程数据库的
  6. sql 查询记录数结果集某个区间内记录
  7. sql server 表结构修改方法
  8. MSSQL数据库排序规则如何更改
  9. mssql2005,2008导出数据字典实现方法
  10. SQL Server正则表达式 替换函数应用详解