上一篇《Android自己定义组件系列【5】——进阶实践(2)》继续对任老师的《可下拉的PinnedHeaderExpandableListView的实现》进行了分析,这一篇计划中间插一段“知识点”,对Android中的事件分发机制进行解析。细心的朋友可能会发现,打开大牛写的Android项目,里面非常多组件都是自己定义的(这就是为什么界面和体验这么吸引你的原因),可是要灵活的去自己定义组件就必须对手势(也就是各种监听)必须熟悉,能处理好事件之间的关系。

先看一段代码:

	@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
Log.i(TAG, "onClick");
}
}); button.setOnTouchListener(new OnTouchListener() { @Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "onTouch down");
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "onTouch move");
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "onTouch up");
break;
default:
break;
}
return false;
}
});
}

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZGF3YW5nYW5iYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

能够看到onTouch方法会被先调用。然后才调用onClick方法,假设我们将上面onTouch方法的返回值改为true,则onClick方法不会被调用,事件将被onTouch方法消费。

还记得前几篇文章中都会使用一个dispatchTouchEvent的方法吗.

public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}

能够看到在dispatchTouchEvent中调用了onTouch方法,所以会先于onClick方法调用。假设onTouch返回true后dispatcheTouchEvent就会直接返回true则不会再运行其它方法。

在Android系统中每一个ViewGroup子类都具有例如以下三个方法:

public boolean dispatchTouchEvent(MotionEvent event)  :用来分发TouchEvent

public boolean onInterceptTouchEvent(MotionEvent event) :用来拦截TouchEvent

public boolean onTouchEvent(MotionEvent event) :处理TouchEvent

<?xml version="1.0" encoding="utf-8"?

>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<com.kris.touch.widget.TouchView
android:id="@+id/view_out"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#fff"
android:gravity="center">
<com.kris.touch.widget.TouchView
android:id="@+id/view_mid"
android:layout_width="300px"
android:layout_height="400px"
android:background="#f00"
android:gravity="center">
<com.kris.touch.widget.TouchView
android:id="@+id/view_center"
android:layout_width="150px"
android:layout_height="150px"
android:background="#000"
android:gravity="center"
android:clickable="true">
</com.kris.touch.widget.TouchView>
</com.kris.touch.widget.TouchView>
</com.kris.touch.widget.TouchView>
</LinearLayout>

首先触摸事件(ACTION_DOWN)发生后,系统调用Activity的dispatchTouchEvent方法。分发事件。

依据触摸事件的坐标,将此事件传递给out(最外层)的dispatchTouchEvent处理。out则调用onInterceptTouchEvent方法推断事件是否由自己来处理。还是向下传递给子View.假设out不处理该事件会依据事件产生坐标分发给它的直接子View.

图中center组件是可点击的(clickable)组件,表示能处理Touch事件,所以center中的onInterceptTouchEvent方法将事件传递给center

TouchEvent中,假设返回值是true,则说明消耗(消费)了这个事件,不会再向下传递。假设返回值是false,则没有消耗事件,会继续传递下去。假设center中不会处理事件(android:clickable="false")。事件不会被center的onTouchEvent消费,则事件会层层逆向回到activity。

关于事件分发机制就先了解到这里。下一篇接着分析......

Android自己定义组件系列【6】——进阶实践(3)的更多相关文章

  1. Android自己定义组件系列【7】——进阶实践(4)

    上一篇<Android自己定义组件系列[6]--进阶实践(3)>中补充了关于Android中事件分发的过程知识.这一篇我们接着来分析任老师的<可下拉的PinnedHeaderExpa ...

  2. Android自己定义组件系列【5】——进阶实践(2)

    上一篇<Android自己定义组件系列[5]--进阶实践(1)>中对任老师的<可下拉的PinnedHeaderExpandableListView的实现>前一部分进行了实现,这 ...

  3. Android自己定义组件系列【4】——自己定义ViewGroup实现双側滑动

    在上一篇文章<Android自己定义组件系列[3]--自己定义ViewGroup实现側滑>中实现了仿Facebook和人人网的側滑效果,这一篇我们将接着上一篇来实现双面滑动的效果. 1.布 ...

  4. Android自己定义组件系列【3】——自己定义ViewGroup实现側滑

    有关自己定义ViewGroup的文章已经非常多了,我为什么写这篇文章,对于刚開始学习的人或者对自己定义组件比較生疏的朋友尽管能够拿来主义的用了,可是要一步一步的实现和了解当中的过程和原理才干真真脱离别 ...

  5. Android自己定义组件系列【5】——高级实践(1)

    在接下来的几篇文章将任老师的博文<您可以下拉PinnedHeaderExpandableListView实现>骤来具体实现.来学习一下大神的代码并记录一下. 原文出处:http://blo ...

  6. Android自己定义组件系列【1】——自己定义View及ViewGroup

    View类是ViewGroup的父类,ViewGroup具有View的全部特性.ViewGroup主要用来充当View的容器.将当中的View作为自己孩子,并对其进行管理.当然孩子也能够是ViewGr ...

  7. Android自己定义组件系列【2】——Scroller类

    在上一篇中介绍了View类的scrollTo和scrollBy两个方法,对这两个方法不太了解的朋友能够先看<自己定义View及ViewGroup> scrollTo和scrollBy尽管实 ...

  8. Android自己定义组件系列【9】——Canvas绘制折线图

    有时候我们在项目中会遇到使用折线图等图形,Android的开源项目中为我们提供了非常多插件,可是非常多时候我们须要依据详细项目自己定义这些图表,这一篇文章我们一起来看看怎样在Android中使用Can ...

  9. Android自己定义组件系列【8】——面膜文字动画

    我们掩盖文字动画Flash中非经货共同体共同,由于Android应用程序开发人员做你想要做这个动画在应用程序中去?本文中,我们看的是如何自己的定义ImageView来实现让一张文字图片实现文字的遮罩闪 ...

随机推荐

  1. 【MySQL】MySQL备份和恢复

    一.为什么要备份数据 在生产环境中我们数据库可能会遭遇各种各样的不测从而导致数据丢失, 大概分为以下几种. 硬件故障 软件故障 自然灾害 黑客攻击 误操作 (占比最大) 所以, 为了在数据丢失之后能够 ...

  2. loj2280 「FJOI2017」矩阵填数

    状压 dp.参考there #include <algorithm> #include <iostream> #include <cstring> #include ...

  3. 用上GIT你一定会爱上他

    前言 Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控 ...

  4. 以前刷过的数位dp

    TOJ1688: Round Numbers Description The cows, as you know, have no fingers or thumbs and thus are una ...

  5. sqlserver的left join优化

    MS sqlserver 对4张表进行left join join字段是varchar类型长度20,也都建了索引,但是光查一个count(Id) 耗时就超过了8秒,数据量只有100多万条,该怎么优化呢 ...

  6. 【转】Bad Smell(代码的坏味道)

    1.Duplicated Code(重复的代码) 臭味行列中首当其冲的就是Duplicated Code.如果你在一个以上的地点看到相同的程序结构,那么当可肯定:设法将它们合而为一,程序会变得更好. ...

  7. CS231n笔记 Lecture 4 Introduction to Neural Networks

    这一讲主要介绍了神经网络,基本内容之前如果学习过Andrew的Machine learning应该也都有所了解了.不过这次听完这一讲后还是有了新的一些认识. 计算图 Computational gra ...

  8. [LOJ#526]「LibreOJ β Round #4」子集

    [LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...

  9. Android默认输入法语言的修改以及SettingsProvider作用

    Android源码中默认的有三种输入法:英文,中文,日文.对应的工程代码路径为:<android_root>/packages/inputmethods/LatinIME/<andr ...

  10. iOS-Core Data基础

    Core Data基础 Core Data是一个API集合,被设计用来简化数据对象的持久存储. 在此先不普及概念,先通过一个简单的案例使用来感受一下Core Data的精妙之处. 在创建工程的时候勾选 ...