`
hao3100590
  • 浏览: 132603 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解

阅读更多

参考文档:

http://blog.csdn.net/liutao5757124/article/details/6097125


首先,看Android的官方文档正解


onInterceptTouchEvent()与onTouchEvent()的机制:

  1. down事件首先会传递到onInterceptTouchEvent()方法


  2. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,

  那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最

  终的目标view的onTouchEvent()处理


  3. 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,

  那么后续的move, up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样

  传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。


  4. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一

  层次的view的onTouchEvent()处理


  5. 如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递

  给该view的onTouchEvent()处理

这是官方文档的说法,要是自己没亲自去写个程序观察哈,基本上没法理解,所以上程序先,然后分析:



布局文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<com.hao.LayoutView1 xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<com.hao.LayoutView2
		android:orientation="vertical" android:layout_width="fill_parent"
		android:layout_height="fill_parent" android:gravity="center">
		<com.hao.MyTextView
			android:layout_width="wrap_content" android:layout_height="wrap_content"
			android:id="@+id/tv" android:text="AB" android:textSize="40sp"
			android:textStyle="bold" android:background="#FFFFFF"
			android:textColor="#0000FF" />
	</com.hao.LayoutView2>
</com.hao.LayoutView1> 

 第一层自定义布局LayoutView1.java

package com.hao;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class LayoutView1 extends LinearLayout {
	 private final String TAG = "LayoutView1"; 
     public LayoutView1(Context context, AttributeSet attrs) { 
    	 super(context, attrs); 
    	 Log.e(TAG,TAG); 
     }
     
     @Override 
     public boolean onInterceptTouchEvent(MotionEvent ev) { 
         int action = ev.getAction(); 
         switch(action){ 
         case MotionEvent.ACTION_DOWN: 
              Log.e(TAG,"onInterceptTouchEvent action:ACTION_DOWN"); 
//              return true; 在这就拦截了,后面的就不会得到事件
              break;
		case MotionEvent.ACTION_MOVE: 
              Log.e(TAG,"onInterceptTouchEvent action:ACTION_MOVE"); 
              break; 
         case MotionEvent.ACTION_UP: 
              Log.e(TAG,"onInterceptTouchEvent action:ACTION_UP"); 
              break; 
         case MotionEvent.ACTION_CANCEL: 
              Log.e(TAG,"onInterceptTouchEvent action:ACTION_CANCEL"); 
              break; 
         } 
         return false; 
     } 

     @Override 
     public boolean onTouchEvent(MotionEvent ev) { 
         int action = ev.getAction(); 
         switch(action){ 
         case MotionEvent.ACTION_DOWN: 
              Log.e(TAG,"onTouchEvent action:ACTION_DOWN"); 
              break; 
         case MotionEvent.ACTION_MOVE: 
              Log.e(TAG,"onTouchEvent action:ACTION_MOVE"); 
              break; 
         case MotionEvent.ACTION_UP: 
              Log.e(TAG,"onTouchEvent action:ACTION_UP"); 
              break; 
         case MotionEvent.ACTION_CANCEL: 
              Log.e(TAG,"onTouchEvent action:ACTION_CANCEL"); 
              break; 
         } 
         return true; 
//         return false;
     } 
     
     @Override 
     protected void onLayout(boolean changed, int l, int t, int r, int b) { 
         // TODO Auto-generated method stub 
         super.onLayout(changed, l, t, r, b); 
     } 

     @Override 
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
         // TODO Auto-generated method stub 
         super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     } 
}

 第二层布局LayoutView2.java

package com.hao;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class LayoutView2 extends LinearLayout {
	
	private final String TAG = "LayoutView2"; 
    public LayoutView2(Context context, AttributeSet attrs) { 
       super(context, attrs); 
       Log.e(TAG,TAG); 
    } 
    
    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
       int action = ev.getAction(); 
       switch(action){ 
       case MotionEvent.ACTION_DOWN: 
           Log.e(TAG,"onInterceptTouchEvent action:ACTION_DOWN");
//           return true;
           break; 
       case MotionEvent.ACTION_MOVE: 
           Log.e(TAG,"onInterceptTouchEvent action:ACTION_MOVE"); 
           break; 
       case MotionEvent.ACTION_UP: 
           Log.e(TAG,"onInterceptTouchEvent action:ACTION_UP"); 
           break; 
       case MotionEvent.ACTION_CANCEL: 
           Log.e(TAG,"onInterceptTouchEvent action:ACTION_CANCEL"); 
           break; 
       } 
       return false; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
       int action = ev.getAction(); 
       switch(action){ 
       case MotionEvent.ACTION_DOWN: 
           Log.e(TAG,"onTouchEvent action:ACTION_DOWN"); 
           break; 
       case MotionEvent.ACTION_MOVE: 
           Log.e(TAG,"onTouchEvent action:ACTION_MOVE"); 
           break; 
       case MotionEvent.ACTION_UP: 
           Log.e(TAG,"onTouchEvent action:ACTION_UP"); 
           break; 
       case MotionEvent.ACTION_CANCEL: 
           Log.e(TAG,"onTouchEvent action:ACTION_CANCEL"); 
           break; 
       } 
//       return true; 
       return false;
    } 
}

 自定义MyTextView.java

package com.hao;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class MyTextView extends TextView {
	private final String TAG = "MyTextView"; 
    public MyTextView(Context context, AttributeSet attrs) { 
       super(context, attrs); 
       Log.e(TAG,TAG); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
       int action = ev.getAction(); 
       switch(action){ 
       case MotionEvent.ACTION_DOWN: 
           Log.e(TAG,"onTouchEvent action:ACTION_DOWN"); 
           break; 
       case MotionEvent.ACTION_MOVE: 
           Log.e(TAG,"onTouchEvent action:ACTION_MOVE"); 
           break; 
       case MotionEvent.ACTION_UP: 
           Log.e(TAG,"onTouchEvent action:ACTION_UP"); 
           break; 
       case MotionEvent.ACTION_CANCEL: 
           Log.e(TAG,"onTouchEvent action:ACTION_CANCEL"); 
           break; 
       } 
       return false; 
//       return true;
    } 

    public void onClick(View v) { 
       Log.e(TAG, "onClick"); 
    } 

    public boolean onLongClick(View v) { 
       Log.e(TAG, "onLongClick"); 
       return false; 
    } 
}

 其实代码很简单,就是自定义了View,在View里面都重写了interceptTouchEvnet (),和onTouchEvent(),然后测试其返回值,对监听的影响,关键是自己动手,逐个测试,并预测结果,等你能预测结果的时候,也就懂了,需要修改的地方就是interceptTouchEvnet 和onTouchEvent的返回值,他们决定了事件监听的流程,下面我画了一张图,如有不足之处欢迎指正,谢谢!


下面是我的正解:

基本的规则是: 
      *1.down事件首先会传递到onInterceptTouchEvent()方法 
      * 
      * 2.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false(不拦截),
      * 那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。 
      *
      * 3.如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true(拦截,那么后面的move,up事件不需要在看因为已经拦截了, 我们直接拿去处理onTouchEvent()就可以了),那么后续的move, up等事件将不再传递给onInterceptTouchEvent(), 而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。 下面例子演示:
      * 1:LayoutView1(31375): onInterceptTouchEvent action:ACTION_DOWN
      * 2:LayoutView2(31375): onInterceptTouchEvent action:ACTION_DOWN
      * 3:LayoutView2(31375): onTouchEvent action:ACTION_DOWN
      * 4:LayoutView1(31375): onInterceptTouchEvent action:ACTION_MOVE
      * 5:LayoutView2(31375): onTouchEvent action:ACTION_MOVE
      * 6:LayoutView1(31375): onInterceptTouchEvent action:ACTION_MOVE
      * 7:LayoutView2(31375): onTouchEvent action:ACTION_MOVE
      * 8:LayoutView1(31375): onInterceptTouchEvent action:ACTION_UP
      * 9:LayoutView2(31375): onTouchEvent action:ACTION_UP
      * 该设置为:
      * onInterceptTouchEvent:LayoutView1为false,LayoutView2为true
      * onTouchEvent:LayoutView2为true
      * 故而事件在LayoutView2(onInterceptTouchEvent:返回true)时被拦截并处理,根据上面说法就是LayoutView2后续的MOVE,UP操作都不在经过onInterceptTouchEvent,直接
      * 交给onTouchEvent处理,结果也的确如此。(见:LayoutView2的3,5,7,9,第一次是onInterceptTouchEvent处理如1,以后交给onTouchEvent)
      * 而LayoutView1都还是要经过onInterceptTouchEvent(见LayoutView1的4,6,8)
      * 
      * 4.如果最终需要处理事件的view的onTouchEvent()返回了false(没能处理这个事件,不能丢在传回来让父继续),
      * 那么该事件将被传递至其上一层次的view的onTouchEvent()处理。 
      * **************************************************************************
      * 感觉像是一个圈,然后一直在找一个能处理这个消息的人,如果找到了就结束,没找到就循环,直到回到发出消息的那个人
      * 注(对下面):没有标注的DOWN表示拦截事件onInterceptTouchEvent,标注了onTouchEvent就是处理事件
      * a.如果都没处理(onInterceptTouchEvent返回false):
A(DOWN)-->B(DOWN)-->C(onTouchEvent DOWN)-->B(onTouchEvent DOWN)-->A(onTouchEvent DOWN),没有执行UP事件,注意有MOVE的话,在DOWN和UP之间,下面的都一样。
      *b. B处理(B的onInterceptTouchEvent返回true):
A(DOWN)-->B(DOWN)-->B(onTouchEvent)-->A(onTouchEvent UP)-->B(onTouchEvent UP)-->(over)
      *
形象说明:如果父亲不拦截消息就传给儿子,如果儿子要这个消息就处理(DOWN),结束,然后有父亲1--父亲2--儿子以此释放消息(UP)。 然是如果儿子对这个消息置之不理,那这个消息又传回父亲,由父亲来处理即。

下面给出了5中情况(不拦截表示onInterceptTouchEvent返回false):
      * 11** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return true)--结束
      * 22** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return false)--回传给父亲2(onTouchEvent return true)--结束
      * 33** 父亲1(LayoutView1不拦截false)---父亲2(LayoutView2不拦截false)--儿子(MyTextView,onTouchEvent return false)--回传给父亲2(onTouchEvent return false)--父亲1(onTouchEvent return true)--结束(如果都没处理不在执行UP ACTION)
      * 44** 父亲1(LayoutView1拦截true)--父亲1(onTouchEvent return true)--结束          (DOWN--DOWN(onTouchEvent)--UP(onTouchEvent))
      * 55** 父亲1(LayoutView1拦截false)--父亲2(LayoutView2拦截true)--父亲2(onTouchEvent return false)--父亲1(onTouchEvent return true)--结束      (DOWN1--DOWN2--DOWN(2 onTouchEvent)--DOWN(1 onTouchEvent)--UP(1 onTouchEvent))(1:父亲2,2:父亲2)
      * 
      * ***************************************************************************
      * 5.如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。 
      */

下面给出一张处理的流程图:


 下附源代码:
  • 大小: 46.5 KB
2
0
分享到:
评论
2 楼 Zero颴 2014-08-19  
大神篇,思路,配图都很清晰,perfect!
1 楼 114624915 2012-02-08  
分析的很详细,

相关推荐

    基于springboot框架的毕业设计系统的开发(完整Java源码+数据库sql文件+项目文档+Java项目编程实战+编程练手好项目).zip

    在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对学生毕业设计信息管理的提升,也为了对学生毕业设计信息进行更好的维护,毕业设计系统的出现就变得水到渠成不可缺少。通过对毕业设计系统的开发,不仅仅可以学以致用,让学到的知识变成成果出现,也强化了知识记忆,扩大了知识储备,是提升自我的一种很好的方法。通过具体的开发,对整个软件开发的过程熟练掌握,不论是前期的设计,还是后续的编码测试,都有了很深刻的认知。 毕业设计系统通过MySQL数据库与Spring Boot框架进行开发,毕业设计系统能够实现教师管理,公告类型管理,班级管理,课题信息管理,任务类型管理,选题申请管理,学院管理,课题任务管理,最终成绩管理,公告信息管理,学生管理等功能。 通过毕业设计系统对相关信息的处理,让信息处理变的更加的系统,更加的规范,这是一个必然的结果。已经处理好的信息,不管是用来查找,还是分析,在效率上都会成倍的提高,让计算机变得更加符合生产需要,变成人们不可缺少的一种信息处理工具,实现了绿色办公,节省社会资源

    hegaojian_WanAndroid_1742851819.zip

    hegaojian_WanAndroid_1742851819.zip

    《基于YOLOv8的违章停车识别系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    使用matlab基于卷积神经网络实现的汉语短句语音识别,输出拼音( 我正在学torch,这个已停止更.zip

    毕业设计

    移动开发_iOS_OpenUrl_快捷方式创建技术_App桌_1742856949.zip

    移动开发_iOS_OpenUrl_快捷方式创建技术_App桌_1742856949.zip

    《基于YOLOv8的体育发展识别系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    uappkit_uapp_1742847088.zip

    app开发

    蓝桥杯python相关资源

    蓝桥杯python相关资源

    招聘_实时聊天_APP_React_Redux_前后端分离_1742854279.zip

    招聘_实时聊天_APP_React_Redux_前后端分离_1742854279.zip

    《基于YOLOv8的玩具产品分析系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    vscode1.98.1版本,适用于macos

    vsco1.98.1版本,适用于macos

    《基于YOLOv8的体育产业监测系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    Kotlin_基础篇教程_函数与类实践_开发参考_1742851889.zip

    Kotlin_基础篇教程_函数与类实践_开发参考_1742851889.zip

    电子发票统计并生成表格

    电子发票统计并生成表格

    IIS重写IIS rewirte的插件ARR(Application Request Routing) Microsoft Application Request Routing 3.0 (x64)

    网上很多都是IIS7的教程ARR,对IIS10来说已经无效了。这个是最新的插件IIS重写IIS rewirte的插件ARR(Application Request Routing)

    linux相关课程学习笔记

    linux系统相关知识、shell编程相关知识、虚拟机安装及配置

    毕业设计神器!最新学生成绩管理系统源码(thinkphp6 框架),让你的毕设轻松出彩

    还在为毕业设计选题纠结?这款基于 thinkphp6 框架 开发的学生成绩管理系统源码,前端采用 X - adminV2.2,功能完备、结构清晰,完美适配毕业设计需求,助你在答辩中脱颖而出! 功能全面,轻松应对毕设考核 全流程管理模块:覆盖系统信息设置、单位信息管理、类别管理,以及学期、班级、学科等基础配置,更有管理员、权限、角色管理,完整呈现系统设计与实现的深度。 智能化成绩处理:支持考试信息自定义,灵活设置学科分数线;一键生成考试号、试卷标签、成绩采集表。多样化成绩录入(在线、表格、扫码枪)、实时查看成绩列表与图表,统计结果以柱形图、折线图、雷达图等形式展示,搭配学生历次成绩对比(表格 + 折线图),充分展现数据处理与分析能力。 精细化权限设计:区分教师、学生双身份登录,按职务、任务分工细化数据权限,体现系统安全性与合理性,为毕设增添专业亮点。 三大核心优势,锁定高分 极简操作,演示无忧:界面简洁直观,操作流程优化至 “三步到位”,答辩演示流畅自然,轻松征服导师。 热门技术栈,学习轻松:基于流行的 thinkphp6 框架,前端 X - adminV2.2,前后端分离。

    《基于YOLOv8的摄像设备分析系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    前端技术_React_TS_豆瓣电影信息_缓存优化扩展_1742857602.zip

    app开发

Global site tag (gtag.js) - Google Analytics