最近在做高德地图的时候,由于用户的要求,不得不用ScrollVew嵌套MapView,虽然很官方要求不建议这样做,但也迫于无奈… 魔高一尺,道高一丈.有什么事是程序员不能解决的,如果有那就是解决两次.
鉴于用到了触摸事件,于是就来总结了Android的触摸事件机制.
首先当用户进行屏幕操作的时候,则有两种情况
-
一是按键事件
-
二是触摸事件
按键事件分为长按和点击事件,过于简单,这里不再进行总结.
触摸事件
触摸事件的组成:
- 一个actionDown
- n个actionMove
- 一个actionUp
- 一个onClick
- 一个onLongClick
- 一个onScroll
Android组件
- 继承 ViewGroupo比如LinearLayout,ScrollView,GridView,extends–>ViewGroup的View
- ViewGroup容器
- 继承于 View不包含其他的View ,如TextView,Edittext,Butto等
下面介绍一个讲的好的一个博客地址:
http://www.trinea.cn/android/touch-event-delivery-mechanism/
MotionEvent
所有Touch事件都被封装成了MotionEvent对象,包括Touch的位置、时间、历史记录以及第几个手指(多指触摸)等。
Android 事件的处理的分类
-
分发(很多人也称作为传递事件) : dispatchTouchEvent函数
-
消费: onTouchEvent函数和OnTouchListener函数
-
拦截:onInterceptTouchEvent函数
我们都知道Android的触摸事件都是从外层传递到内层:由最外层的Activity——>ViewGroup——> ViewGroupo——>…….View.
第一触摸事件传递的开始一定是Activity;
第二传递方式是通过隧道方式传递;
第三一直传递到一个最外层的View,也就是顶级View,由该View的这个方法来进行分发。
对于Activity来说:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isFlag = super.dispatchTouchEvent(ev);
return isFlag;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean isFlag = super.onTouchEvent(event);
return isFlag;
}
对于ViewGroup来说:
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean isFlag =super.onTouchEvent(event);
return isFlag;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
boolean isFlag =super.onInterceptTouchEvent(event);
return isFlag;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
boolean isFlag =super.dispatchTouchEvent(event);
return isFlag;
}
对于View来说和Activity一样,只有消费和拦截
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isFlag = super.dispatchTouchEvent(ev);
return isFlag;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean isFlag = super.onTouchEvent(event);
return isFlag;
}
http://www.open-open.com/lib/view/open1463016891525.html
android中的Touch事件都是从ACTION_DOWN开始的:
单手指操作:ACTION_DOWN—ACTION_MOVE—-ACTION_UP
多手指操作:ACTION_DOWN—ACTION_POINTER_DOWN—ACTION_MOVE–ACTION_POINTER_UP—ACTION_UP.
如果都不进行拦截,都不消费的基本流程图:
下面我们就用案例进行分析:
activity—-》ViewGroup(MyLinearLayout)—》ViewGroup(MySubView)
MyLinearLayout的dispatchTouchEvent返回false。
打印结果:
过程及结果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分发给 TouchEventFather 控件的dispatchTouchEvent;
而该TouchEventFather 控件的 dispatchTouchEvent 返回 false,表示对获取到的事件停止向下传递,同时也不对该事件进行消费;
由于 TouchEventFather 获取的事件直接来自 TouchEventActivity ,则会将事件返回给 TouchEventActivity 的 onTouchEvent 进行消费;
最后直接由 TouchEventActivity 来响应手指移动和抬起事件。
MyLinearLayout的dispatchTouchEvent返回true。
打印结果:
过程及结果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分发给 TouchEventFather 控件的 dispatchTouchEvent;
而该TouchEventFather 控件的 dispatchTouchEvent 返回 true,表示分发事件到 TouchEventFather 控件并由该控件的 dispatchTouchEvent 进行消费;
又因为TouchEventActivity 不断的分发事件到 TouchEventFather 控件的 dispatchTouchEvent,而 TouchEventFather 控件的 dispatchTouchEvent 也不断的将获取到的事件进行消费。
MyLinearLayout的onInterceptTouchEvent返回true。
打印结果:
过程及结果分析:
事件首先由 TouchEventActivity 的 dispatchTouchEvent 方法分发给 TouchEventFather 控件的 dispatchTouchEvent;
而该TouchEventFather 控件的 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev),表示对事件进行分发并向下传递给 TouchEventFather 控件的 onInterceptTouchEvent 方法;
而该方法返回 true 表示对所获取到的事件进行拦截并将事件传递给 TouchEventFather 控件的 onTouchEvent 进行处理,TouchEventFather 控件的 onTouchEvent 返回 super.onTouchEvent(ev) 表示对事件没有