昨天做东西做到触摸事件冲突,以前也经常碰到事件冲突,想到要研究一下Android的事件冲突机制,于是从昨天开始到今天整整一天时间都要了解这方面的知识,这才懂了安卓的触摸和点击事件的机制。探究如下:

  首先重写三个View布局,用来做测试:

    

package com.example.yzj.android_8_10;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout; /**
* Created by YZJ on 2016/8/10.
*/
public class V1 extends LinearLayout{ public V1(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v("msg", "v1-dispatch");
return super.dispatchTouchEvent(ev);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("msg","v1-onIntercept");
return false;
} @Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("msg","v1-onTouch");
return false;
}
}
package com.example.yzj.android_8_10;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout; /**
* Created by YZJ on 2016/8/10.
*/
public class V2 extends LinearLayout{ public V2(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v("msg", "v2-dispatch");
return super.dispatchTouchEvent(ev);
} @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("msg","v2-onIntercept");
return false;
} @Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("msg","v2-onTouch");
return false;
}
}
package com.example.yzj.android_8_10;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View; /**
* Created by YZJ on 2016/8/10.
*/
public class V3 extends View { public V3(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v("msg", "v3-dispatch");
return super.dispatchTouchEvent(ev);
}
// @Override
// public boolean onTouchEvent(MotionEvent event) {
// Log.v("msg","v3-onTouch");
// return true;
// }
}

然后是MainActivity的xml代码:

<?xml version="1.0" encoding="utf-8"?>
<com.example.yzj.android_8_10.V1 xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/v1"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorAccent"
tools:context="com.example.yzj.android_8_10.MainActivity">
<com.example.yzj.android_8_10.V2
android:layout_gravity="center"
android:id="@+id/v2"
android:layout_width="400dp"
android:layout_height="400dp"
android:background="@color/colorPrimaryDark">
<com.example.yzj.android_8_10.V3
android:background="#F00000"
android:id="@+id/v3"
android:layout_gravity="center"
android:layout_width="300dp"
android:layout_height="300dp"></com.example.yzj.android_8_10.V3>
</com.example.yzj.android_8_10.V2>
</com.example.yzj.android_8_10.V1>

    

  然后是MainActivity的JAVA代码:

  

package com.example.yzj.android_8_10;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View; public class MainActivity extends AppCompatActivity {
View v1, v2, v3; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.v("msg", "MainActivity-dispatch");
return super.dispatchTouchEvent(ev);
} @Override
public boolean onTouchEvent(MotionEvent event) {
Log.v("msg", "MainActivity-onTouch");
return false;
} private void init() {
v1 = findViewById(R.id.v1);
v2 = findViewById(R.id.v2);
v3 = findViewById(R.id.v3);
v3.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
Log.v("msg","Action_Down");
break;
case MotionEvent.ACTION_MOVE:
Log.v("msg","Action_Move");
break;
case MotionEvent.ACTION_UP:
Log.v("msg","Action_Up");
break;
}
return false;
}
});
v3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v("msg","v3-OnClick");
}
});
}
}

  下面来详细说明:

      Android的触摸和点击事件其实是绑定在一起的,或者说的更详细一点OnClick是依赖于OnTouch的,这点在稍后会详细的说明。先介绍一下消息传递的流程,Android和WINDOWS的消息传递机制是一样的,都是冒泡传递,即从最底层,往上依次传递,在我的代码中是从MainActivity->v1->v2->v3,这样传递消息,而处理起来,或者用专业术语叫消费(google的API文档中是用消费这个词...),消费则是相反的方向,即从上面最小的V3开始,逐渐传递到MainActivity,v3->v2->v1->MainActivity.

下面附上代码运行的结果:

      //事件传递过程

08-10 17:40:06.182 3926-3926/? V/msg: MainActivity-dispatch
08-10 17:40:06.182 3926-3926/? V/msg: v1-dispatch
08-10 17:40:06.182 3926-3926/? V/msg: v1-onIntercept
08-10 17:40:06.182 3926-3926/? V/msg: v2-dispatch
08-10 17:40:06.182 3926-3926/? V/msg: v2-onIntercept
08-10 17:40:06.182 3926-3926/? V/msg: v3-dispatch

      //事件消费过程
08-10 17:40:06.182 3926-3926/? V/msg: v3-OnTouch
08-10 17:40:06.182 3926-3926/? V/msg: v2-onTouch
08-10 17:40:06.182 3926-3926/? V/msg: v1-onTouch
08-10 17:40:06.182 3926-3926/? V/msg: MainActivity-onTouch

可以清楚的看出,事件的传递过程的方向和消费过程的方向。

  

    

跟touch事件相关的3个方法:
public boolean dispatchTouchEvent(MotionEvent ev);    //用来分派event
public boolean onInterceptTouchEvent(MotionEvent ev); //用来拦截event
public boolean onTouchEvent(MotionEvent ev);          //用来处理event
Activity类: Activity dispatchTouchEvent();
onTouchEvent();
View容器(ViewGroup的子类): FrameLayout、LinearLayout……
ListView、ScrollVIew……
dispatchTouchEvent();
onInterceptTouchEvent();
onTouchEvent();
View控件(非ViewGroup子类): Button、TextView、EditText…… dispatchTouchEvent();
onTouchEvent();

   

个方法的用法:
 
 
 
 
 
dispatchTouchEvent() 用来分派事件。
其中调用了onInterceptTouchEvent()和onTouchEvent(),一般不重写该方法
onInterceptTouchEvent() 用来拦截事件。
ViewGroup类中的源码实现就是{return false;}表示不拦截该事件,
事件将向下传递(传递给其子View);
若手动重写该方法,使其返回true则表示拦截,事件将终止向下传递,
事件由当前ViewGroup类来处理,就是调用该类的onTouchEvent()方法
onTouchEvent() 用来处理事件。
返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View);
返回false表示不能处理,则把事件传递给其父View的onTouchEvent()方法来处理

      

 
 
 
          下面在把ACION_DOWN,MOVE,UP,ONCLICK的顺序写下来,测试结果如下:

08-10 17:49:30.182 5125-5125/? V/msg: MainActivity-dispatch
08-10 17:49:30.182 5125-5125/? V/msg: v1-dispatch
08-10 17:49:30.182 5125-5125/? V/msg: v1-onIntercept
08-10 17:49:30.182 5125-5125/? V/msg: v2-dispatch
08-10 17:49:30.182 5125-5125/? V/msg: v2-onIntercept
08-10 17:49:30.182 5125-5125/? V/msg: v3-dispatch
08-10 17:49:30.182 5125-5125/? V/msg: Action_Down
08-10 17:49:30.182 5125-5125/? V/msg: v2-onTouch
08-10 17:49:30.182 5125-5125/? V/msg: v1-onTouch
08-10 17:49:30.182 5125-5125/? V/msg: MainActivity-onTouch
08-10 17:49:30.202 5125-5125/? V/msg: MainActivity-dispatch
08-10 17:49:30.202 5125-5125/? V/msg: MainActivity-onTouch
08-10 17:49:30.232 5125-5125/? V/msg: MainActivity-dispatch
08-10 17:49:30.232 5125-5125/? V/msg: MainActivity-onTouch
08-10 17:49:30.242 5125-5125/? V/msg: MainActivity-dispatch
08-10 17:49:30.242 5125-5125/? V/msg: MainActivity-onTouch

      最后借鉴几张别人总结的好图,可以更直观的看:

        如果在V3处ONTOUCH返回的flase,那么 

 

    其他的几种情况请读者自己测试,本文就写到这里。

      在此感谢http://blog.csdn.net/morgan_xww/article/details/9372285/给我的提示。

      希望大家自己测试一下,毕竟自己亲手动过的记得比较牢。

android 事件分发机制详解(OnTouchListener,OnClick)的更多相关文章

  1. Android事件分发机制详解

    事件分发机制详解 一.基础知识介绍 1.经常用的事件有:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP等 2 ...

  2. Android事件分发机制详解(2)----分析ViewGruop的事件分发

    首先,我们需要 知道什么是ViewGroup,它和普通的View有什么区别? ViewGroup就是一组View的集合,它包含很多子View和ViewGroup,是Android 所有布局的父类或间接 ...

  3. Android事件分发机制详解(1)----探究View的事件分发

    探究View的事件分发 在Activity中,只有一个按钮,注册一个点击事件 [java] view plaincopy button.setOnClickListener(new OnClickLi ...

  4. Android事件传递机制详解及最新源码分析——ViewGroup篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...

  5. Android开发——事件分发机制详解

    0. 前言   转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52566965 深入学习事件分发机制,是为了解决在Android开发中 ...

  6. Android View 事件分发机制详解

    想必很多android开发者都遇到过手势冲突的情况,我们一般都是通过内部拦截和外部拦截法解决此类问题.要想搞明白原理就必须了解View的分发机制.在此之前我们先来了解一下以下三个非常重要的方法: di ...

  7. Android事件传递机制详解及最新源码分析——View篇

    摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 对于安卓事件传递机制相信绝大部分开发者都听说过或者了解过,也是面试中最常问的问题之一.但是真正能从源码角度理解具体事件传递流程的相信并不多, ...

  8. IOS 触摸事件分发机制详解

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:MelonTeam 前言 很多时候大家都不关心IOS触摸事件的分发机制的实现原理,当遇到以下几种情形的时候你很可能抓破头皮都找不到解决方案 ...

  9. 【Android面试查漏补缺】之事件分发机制详解

    前言 查漏补缺,查漏补缺,你不知道哪里漏了,怎么补缺呢?本文属于[Android面试查漏补缺]系列文章第一篇,持续更新中,感兴趣的朋友可以[关注+收藏]哦~ 本系列文章是对自己的前段时间面试经历的总结 ...

随机推荐

  1. 自定义基于 VLC 的视频播放器

    前言(蛋疼的背景故事) 前段时间,接了一个小项目,有个需求是要在系统待机一段时间以后,循环播放 MV(类似于 Windows 系统的屏幕保护). 听到这个需求,我首先想到的是 MediaPlayer ...

  2. AngularJS过滤器filter-保留小数,小数点-$filter

    AngularJS      保留小数 默认是保留3位 固定的套路是 {{deom | number:4}} 意思就是保留小数点 的后四位 在渲染页面的时候 加入这儿个代码 用来精确浮点数,指定小数点 ...

  3. 深入理解BFC

    定义 在解释BFC之前,先说一下文档流.我们常说的文档流其实分为定位流.浮动流和普通流三种.而普通流其实就是指BFC中的FC.FC是formatting context的首字母缩写,直译过来是格式化上 ...

  4. Android N开发 你需要知道的一切

    title: Android N开发 你需要知道的一切 tags: Android N,Android7.0,Android --- 转载请注明出处:http://www.cnblogs.com/yi ...

  5. 流程开发Activiti 与SpringMVC整合实例

    流程(Activiti) 流程是完成一系列有序动作的概述.每一个节点动作的结果将对后面的具体操作步骤产生影响.信息化系统中流程的功能完全等同于纸上办公的层级审批,尤其在oa系统中各类电子流提现较为明显 ...

  6. 通过VMware的PowerCLI配置集群内指定主机的vMotion功能

    PowerCLI是VMware开发的基于微软(MSFT)的PowerShell的命令行管理vSphere的实现,因此在批量化操作方面CLI会减轻很多GUI环境下的繁琐重复劳作. 现有场景中有大量的物理 ...

  7. CSS 3学习——box-sizing和背景

    box-sizing 在CSS 2中设置元素的width和height仅仅是设置了元素内容区的宽和高,元素实际的尺寸是margin + border + padding + 内容区. CSS 3(截止 ...

  8. STM32F429 LCD程序移植

    STM32F429自带LCD驱动器,这一具有功能给我等纠结于屏幕驱动的程序员带来了很大的福音.有经验的读者一定有过这样的经历,用FSMC驱动带由控制器的屏幕时候,一旦驱动芯片更换,则需要重新针对此驱动 ...

  9. 说一说python的牛比与不爽

    本人写了10年php了.今年开始改写python了.不是说php有什么不好,php在自己的势力范围内还是很牛比的.只是我已经不能满足于php那两亩地了. 习惯了脚本,所以很自然就过度到python了. ...

  10. 28个你必须知道的HTML5的新特性,技巧以及技术

    崭新新的页面布局 传统的: HTML5: 1. 新的Doctype 尽管使用<!DOCTYPE html>,即使浏览器不懂这句话也会按照标准模式去渲染 2. Figure元素 用<f ...