zoukankan      html  css  js  c++  java
  • Android事件处理第一节(View对Touch事件的处理)

    http://ipjmc.iteye.com/blog/1694146

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

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

    Java代码  收藏代码
    1. public boolean dispatchTouchEvent(MotionEvent ev);  
    2. public boolean onTouchEvent(MotionEvent ev);  



            二、在ViewGroup里,有三个回调函数 

    Java代码  收藏代码
    1. public boolean dispatchTouchEvent(MotionEvent ev);  
    2. public boolean onInterceptTouchEvent(MotionEvent ev);  
    3. public boolean onTouchEvent(MotionEvent ev);  



            三、在Activity里,有两个回调函数 

    Java代码  收藏代码
    1. public boolean dispatchTouchEvent(MotionEvent ev);  
    2. public boolean onTouchEvent(MotionEvent ev);  




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

        

    Java代码  收藏代码
    1. public boolean dispatchTouchEvent(MotionEvent event) {  
    2.         if (mInputEventConsistencyVerifier != null) {  
    3.             mInputEventConsistencyVerifier.onTouchEvent(event, 0);  
    4.         }  
    5.   
    6.         if (onFilterTouchEventForSecurity(event)) {  
    7.             //noinspection SimplifiableIfStatement  
    8.             ListenerInfo li = mListenerInfo;  
    9.             if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  
    10.                     && li.mOnTouchListener.onTouch(this, event)) {  
    11.                 return true;  
    12.             }  
    13.   
    14.             if (onTouchEvent(event)) {  
    15.                 return true;  
    16.             }  
    17.         }  
    18.   
    19.         if (mInputEventConsistencyVerifier != null) {  
    20.             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);  
    21.         }  
    22.         return false;  
    23.     }  


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

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

    Java代码  收藏代码
    1. package com.ipjmc.vgdemo;  
    2.   
    3. import android.content.Context;  
    4. import android.graphics.Bitmap;  
    5. import android.graphics.Canvas;  
    6. import android.graphics.Paint;  
    7. import android.util.AttributeSet;  
    8. import android.util.Log;  
    9. import android.view.MotionEvent;  
    10. import android.view.View;  
    11.   
    12. public class CustomView extends View {  
    13.   
    14.     private static final String TAG = "CustomView";  
    15.     private int mLastX, mLastY;  
    16.     private int mCurrX, mCurrY;  
    17.       
    18.     private Bitmap mBitmap;  
    19.     private Paint mPaint;  
    20.       
    21.     public CustomView(Context context, AttributeSet attrs) {  
    22.         super(context, attrs);  
    23.         mPaint = new Paint();  
    24.         mPaint.setStrokeWidth(6);  
    25.     }  
    26.   
    27.     @Override  
    28.     protected void onDraw(Canvas canvas) {  
    29.         super.onDraw(canvas);  
    30.           
    31.         int width = getWidth();  
    32.         int height = getHeight();  
    33.           
    34.         if (mBitmap == null) {  
    35.             mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);  
    36.         }  
    37.           
    38.         Canvas tmpCanvas = new Canvas(mBitmap);  
    39.         tmpCanvas.drawLine(mLastX, mLastY, mCurrX, mCurrY, mPaint);  
    40.         canvas.drawBitmap(mBitmap, 0, 0, mPaint);  
    41.     }  
    42.       
    43.     @Override  
    44.     public boolean dispatchTouchEvent(MotionEvent event) {  
    45.         Utils.log(TAG, "dispatchTouchEvent", event.getAction());  
    46.         return super.dispatchTouchEvent(event);  
    47.     }  
    48.       
    49.       
    50.     @Override  
    51.     public boolean onTouchEvent(MotionEvent event) {  
    52.           
    53.         mLastX = mCurrX;  
    54.         mLastY = mCurrY;  
    55.         mCurrX = (int) event.getX();  
    56.         mCurrY = (int) event.getY();  
    57.           
    58.         switch (event.getAction()) {  
    59.         case MotionEvent.ACTION_DOWN:  
    60.             mLastX = mCurrX;  
    61.             mLastY = mCurrY;  
    62.             break;  
    63.         default:  
    64.             break;  
    65.         }  
    66.           
    67.         invalidate();  
    68.         return true;  
    69.     }  
    70. }  


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



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

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

    Java代码  收藏代码
    1. @Override  
    2.     public boolean dispatchTouchEvent(MotionEvent event) {  
    3.         Utils.log(TAG, "dispatchTouchEvent", event.getAction());  
    4.         super.dispatchTouchEvent(event);  
    5.         return false;  
    6.     }  


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


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

    Java代码  收藏代码
    1. public boolean dispatchTouchEvent(MotionEvent event) {  
    2.         Utils.log(TAG, "dispatchTouchEvent", event.getAction());  
    3.         super.dispatchTouchEvent(event);  
    4.           
    5.         if (event.getAction() == MotionEvent.ACTION_DOWN) {  
    6.             return true;  
    7.         }  
    8.           
    9.         return false;  
    10.     }  


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

  • 相关阅读:
    ASP.NET解决Sqlite日期类型问题:该字符串未被识别为有效的 DateTime
    无法定位程序输入点_except_handler4_common于动态链接库msvcrt.dll上
    无意中找到的一个“通用不间断滚动JS封装类”
    sqlite中字符串的连接操作
    dhtmlxTree介绍
    项目之小模块有感
    JAVA中创建对象的四种方式
    Eclipse插件汇集(未完善)
    apache之beanutils包比较工具类ComparatorUtils
    Eclipse之maven插件m2eclips
  • 原文地址:https://www.cnblogs.com/feng9exe/p/5708724.html
Copyright © 2011-2022 走看看