Android触摸事件
来源:互联网 发布:淘宝设置信用卡支付 编辑:程序博客网 时间:2024/05/18 02:29
1 Android中三种比较重要的类型动作ACTION_DOWN,ACTION_MOVE,ACTION_UP。
2 ACTION_DOWN事件未处理时,后面的ACTION_MOVE,ACTION_UP也不会处理,,否则就成了无源之水,前面的动作是后面两个动作的基础。
3 ACTION_CANCEL发生的条件。若是ACTION_DOWN(或者ACTION_MOVE)时父View 的onInterceptTouchEvent返回false ,而在ACTION_MOVE(或者ACTION_UP)时父View onInterceptTouchEvent返回true,则会触发子View的ACTION_CANCEL事件。
3 ViewGroup包括
4 dispatchTouchEvent——》onInterceptTouchEvent——》onTouchEvent,按照此顺序进行动作的传递处理,尤其注意的是,每一种类型动作都是独立的从上到下传递
处理完成之后,然后在进行下一类型动作的传递处理。
5 对于View而言,触摸事件有两种处理方式,1:setOnTouchListener(OnTouchListener l);2 onTouchEvent()
5 onClick ,onLongClick等点击事件都是在onTouchEvent()中调用的。
6当你点击了某个控件,首先会去调用该控件所在布局的dispatchTouchEvent方法,然后在布局的dispatchTouchEvent方法中找到被点击的相应控件,再去调用该控件的dispatchTouchEvent方法。
每一个view的event方法有且只会被调用一次,而他们的返回值true:代表我要用这次这个touch事件,那么down事件之后的move、up都会传入此event方法;若返回值为false:代表不需要这个touch事件,那么如果有down事件经过之后的move、up事件都不会再被传入。
dispatchTouchEvent默认返回值:true
onInterceptTouchEvent默认返回值:false
onTouchEvent默认返回值:最外部可被点击的View默认值为true,父容器的默认值为false
8 若没有重写View.dispatchTouchEvent(),那么View.onTouchEvent()返回true,则父view认为子View消费了此次事件,即父View不会调用自己的onTouch()方法。但是若重写了View.dispatchTouchEvent(),并且返回true,则不管View.onTouchEvent()是否返回true,父View都会认为子View消费了此次事件,也就不会调用父View的onTouchEvent()方法,这是因为onTouchEvent()最终都是在dispatchTouchEvent()中调用的,因此确认一次事件最终是否被消费,都是通过dispatchTouchEvent()的返回值进行判断的。
8 在Activity的dispatchTouchEvent方法中直接将事件指定给了特定组件,如下:
<span style="font-size:18px;">public class MainActivity extends Activity { private Button myButton; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); myButton=(Button) findViewById(R.id.button); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return myButton.dispatchTouchEvent(ev); }@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_MOVE:break;case MotionEvent.ACTION_UP:break;}return super.onTouchEvent(event);}}</span>
ViewGroup里含有:dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent
View里只含有:dispatchTouchEvent、onTouchEvent
dispatchTouchEvent无论return true还是return false,事件都不再进行分发,
只有当其return super.dispatchTouchEvent(ev),才表明其具有向下层分发的愿望,
但是是否能够分发成功,则需要经过事件拦截onInterceptTouchEvent的审核。
一 Activity:包括dispatchTouchEvent()和onTouchEvent()两种处理
1 dispatchTouchEvent()
public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getWindow().superDispatchTouchEvent(ev)) {//if里面的语句很重要,所有的事件分发和处理都是从此处开始的 return true; } return onTouchEvent(ev); }
(1)onUserInteraction()方法是空方法,暂且不管.
- * (2)调用getWindow().superDispatchTouchEvent(ev)
* 即调用了PhoneWindow的superDispatchTouchEvent(ev)方法.
* @Override
* public boolean superDispatchTouchEvent(MotionEvent event) {
* return mDecor.superDispatchTouchEvent(event);
* }
* 在该方法中会调用DecorView的superDispatchTouchEvent(event)方法.
* DecorView是一个定义在PhoneWindow中的一个内部类.定义如下:
* private final class DecorView extends FrameLayout implements RootViewSurfaceTaker{}
* 发现没有,它是继承自FrameLayout的?其实,系统会对任意一个Activity的最外层布局嵌套一个Framindow().superDispatchTouchEvent(ev)方法返回的false即事件未被消费.
* 此时if条件eLayout.
* 嗯哼,是不是暗示着什么........
* 继续看DecorView的superDispatchTouchEvent(event)方法,源码如下:
* public boolean superDispatchTouchEvent(MotionEvent event) {
* return super.dispatchTouchEvent(event);
* }
* 在该方法中方法中调用了super.dispatchTouchEvent(event);
* 即调用了FrameLayout(也就是ViewGroup)的dispatchTouchEvent(event);
* 剩下的流程就和ViewGroup的事件分发一致了.
* (3)如果getW不满足,于是代码继续往下执行那么就会调用onTouchEvent(ev)
* 也就是Activity的onTouchEvent(MotionEvent event).
2 onTouchEvent()
- 二 ViewGroup:包括dispatchTouchEvent(),onInterceptTouchEvent()和onTouchEvent()三种处理
三 View:包括dispatchTouchEvent()和onTouchEvent()两种处理
1. dispatchTouchEvent()
* Pass the touch screen motion event down to the target view, or this
* view if it is the target.
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
*/
public boolean dispatchTouchEvent(MotionEvent event) {
if (!onFilterTouchEventForSecurity(event)) {
return false;
}
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
2. onTouchEvent()
/** * Implement this method to handle touch screen motion events. * * @param event The motion event. * @return True if the event was handled, false otherwise. */ public boolean onTouchEvent(MotionEvent event) { final int viewFlags = mViewFlags;
<span style="white-space:pre"></span>//<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14.166666030883789px; line-height: 25.989582061767578px;">如果当前View是Disabled状态且是可点击则会消费掉事件(return true),如果不可点击则不消费此次事件(return false);</span> if ((viewFlags & ENABLED_MASK) == DISABLED) { // A disabled view that is clickable still consumes the touch // events, it just doesn't respond to them. return (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)); }
<span style="white-space:pre"></span>//<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14.166666030883789px; line-height: 25.989582061767578px;">TouchDelegate是用来增加控件的触摸范围的,<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14.166666030883789px; line-height: 25.989582061767578px;">假设有两个View,分别是v1,v2,我们可以通过v1的setTouchDelegate(bounds, v2)来委 //派触摸事件,其中bounds是一个Rect。v1中,落在这个范围的TouchEvent都会传给v2。</span></span> if (mTouchDelegate != null) { if (mTouchDelegate.onTouchEvent(event)) { return true; } } if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) { switch (event.getAction()) { case MotionEvent.ACTION_UP: boolean prepressed = (mPrivateFlags & PREPRESSED) != 0; if ((mPrivateFlags & PRESSED) != 0 || prepressed) { // take focus if we don't have it already and we should in // touch mode. boolean focusTaken = false; if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); } if (!mHasPerformedLongPress) { // This is a tap, so remove the longpress check removeLongPressCallback(); // Only perform take click actions if we were in the pressed state if (!focusTaken) { // Use a Runnable and post this rather than calling // performClick directly. This lets other visual state // of the view update before click actions start. if (mPerformClick == null) { mPerformClick = new PerformClick(); } if (!post(mPerformClick)) { performClick(); } } } if (mUnsetPressedState == null) { mUnsetPressedState = new UnsetPressedState(); } if (prepressed) { mPrivateFlags |= PRESSED; refreshDrawableState(); postDelayed(mUnsetPressedState, ViewConfiguration.getPressedStateDuration()); } else if (!post(mUnsetPressedState)) { // If the post failed, unpress right now mUnsetPressedState.run(); } removeTapCallback(); } break; case MotionEvent.ACTION_DOWN: if (mPendingCheckForTap == null) { mPendingCheckForTap = new CheckForTap(); } mPrivateFlags |= PREPRESSED;
<span style="white-space:pre"></span>//<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14.166666030883789px; line-height: 25.989582061767578px;">设置mHasPerformedLongPress=false;表示长按事件还未触发</span> mHasPerformedLongPress = false;
<span style="white-space:pre"></span>//<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14.166666030883789px; line-height: 25.989582061767578px;">发送一个延迟为ViewConfiguration.getTapTimeout()的延迟消息,到达延时时间后会执行CheckForTap()里面的run方法</span>
<span style="white-space:pre"></span>//长按事件在<span style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14.166666030883789px; line-height: 25.989582061767578px;">CheckForTap中处理</span> postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); break; case MotionEvent.ACTION_CANCEL: mPrivateFlags &= ~PRESSED; refreshDrawableState(); removeTapCallback(); break; case MotionEvent.ACTION_MOVE: final int x = (int) event.getX(); final int y = (int) event.getY(); // Be lenient about moving outside of buttons int slop = mTouchSlop; if ((x < 0 - slop) || (x >= getWidth() + slop) || (y < 0 - slop) || (y >= getHeight() + slop)) { // Outside button removeTapCallback(); if ((mPrivateFlags & PRESSED) != 0) { // Remove any future long press/tap checks removeLongPressCallback(); // Need to switch from pressed to not pressed mPrivateFlags &= ~PRESSED; refreshDrawableState(); } } break; } return true; } return false; }
- Android:处理触摸事件
- android 触摸事件
- Android Touch 触摸事件
- android触摸事件传递
- Android 触摸事件大全
- android触摸语音事件
- android的触摸事件
- Android 手势&触摸事件
- Android 手势&触摸事件
- Android触摸事件传递
- Android 手势&触摸事件
- Android触摸事件机制
- 获取android触摸事件
- Android触摸事件机制
- Android 手势&触摸事件
- android 事件触摸
- Android触摸事件
- Android 手势&触摸事件
- x86架构综述
- AngularJs ng-options 无法设置value的问题
- 谷歌浏览器插件 离线安装 AXURE RP EXTENSION For Chrome
- Controller角色和选举
- js中split函数的使用方法说明
- Android触摸事件
- AspNet MVC4 教学-11:Asp.Net MVC4 默认Authorize及自定义Authorize快速Demo
- sqlite3 not found的解决办法
- matlab cell
- linux telnet 之 telnet: Unable to connect to remote host: Connection refused
- linux下TCP/socket编程实例
- 判断三极管是否可以放大交流信号的方法
- 发现数据库查询表空间使用率语句执行的很慢
- leetcode| Happy Number