自定义View基础(二)事件分发机制
来源:互联网 发布:喀秋莎录屏软件破解版 编辑:程序博客网 时间:2024/06/06 15:42
消息事件传递流程
对于一个根ViewGroup来说,当事件发生时,会调用它的dispatchTouchEvent(MotionEvent ev)方法进行事件的分发,判断根 ViewGroup的onInterceptTouchEvent(MotionEvent ev)是否为true,return true则会把事件拦截交给这个ViewGroup处理,调用该ViewGrouponTouchEvent方法,onTouchEvent()如果return false则会把事件传递给上一层的ViewGroup的onTouchEvent方法执行;onInterceptTouchEvent方法return false则会把事件传递给下一层View(ViewGroup)的dispatchTouchEvent(MotionEvent ev)直到消息最终被处理
//伪代码: @Override public boolean dispatchTouchEvent(MotionEvent ev) { if(onInterceptTouchEvent(ev)){ return onTouchEvent(ev); }else{ //最底层ViewGroup时,遍历所有的子view,判断事件发生的点位于哪个子View,调用该view的onTouEvent方法, //(如果是ViewGroup则调用子viewGroup的dispatchTouchEvent方法),如果事件发生的点没有位于任何子view, //那么由该ViewGroup来处理该事件,调用ViewGroup的onTouchEvent()方法 return child.dispatchTouchEvent(MotionEvent ev); } }
主意:View是没有dispatchTouchEvent(MotionEvent ev)和onInterceptTouchEvent(MotionEvent ev)方法
消息传递顺序
事件总是先传给Activity的dispatchTouchEvent(MotionEvent ev)进行事件分发,再传给Window最后Window再传给顶级View,
然后顶级View会根据事件分发机制去分发事件,如果所有元素都不去处理这个事件,即onTouchEvent方法return false,则Activity的onTouchEvent方法会被调用
OnTouchListener,onTouchEvent与OnClickListener,OnLongClickListener的关系
当一个View需要处理事件时,会先判断是否设置onTouchListener,如果设置了就调用onTouch方法,onTouch方法
如果return true,本次事件被消耗掉;如果onTouch返回false,则回调用onTouchEvent,返回onTouchEvent的返回值
在onTouchEvent内部,如果设置了onClickListener就会去调用onClick方法
总的来说,就是给View设置onTouchListener它的优先级比onTouchEvent要高一些,onClickListener的优先级最低;
OnLongClickListener的onLongClick方法返回值:
如果返回值为true的话这个点击事件会被长点击独占,如果返回值为false会同时触发OnClickListener点击事件
OnCLick/onLongClick要在down和up事件响应后(手指按下和抬起两个操作,我们可以理解为一次Click)
ACTION_DOWN->ACTION_UP->onCLick/onLongClick
-响应ACTION_DOWN事件如果返回false--那么同一序列中的其他事件 将会由它的父元素的onTouchEvent来处理
true--代表View接受此按压动作,然后就是执行ACTION_UP
-ACTION_UP:onLongClick是在ACTION_UP之前,而onClick的发生是在ACTION_UP后,因此同一次用户touch操作
就有可能既发生onLongClick又发生onClick。我们如果在onLongClick()方法的最后return true,那么onClick事件就没有机会被触发了。
滑动冲突的解决方式
a.外部解决法:父容器对事件判断是否拦截
public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub boolean result=false; switch(ev.getAction()){ case MotionEvent.ACTION_DOWN: firstX=(int) ev.getX(); firstY=(int) ev.getY(); break; case MotionEvent.ACTION_MOVE: //手指在屏幕上水平移动的绝对值 int disX=(int) Math.abs(ev.getX()-firstX); //手指在屏幕上竖直移动的绝对值 int disY=(int) Math.abs(ev.getY()-firstY); if(disX>disY&&disX>10){ result=true; } break; case MotionEvent.ACTION_UP: break; } return result; }
b.内部解决法:父容器不拦截任何事件,任何的事件都传递给子元素,如果子元素需要此事件就消耗掉,否则就由父容器进行处理。
对于底层的View来说,有一种方法可以阻止父层的View截获touch事件,就是调用getParent().requestDisallowInterceptTouchEvent(true);方法。一旦底层View收到touch的action后调用这个方法那么父层View就不会再调用onInterceptTouchEvent了,也无法截获以后的action。
public boolean dispatchTouchEvent(MotionEvent event){ switch(event.getAction()){ case MotionEvent.ACTION_DOWN: //父控件就不会拦截ListView的滑动事件 parent.requestDisallowInterceptTouchEvent(true); break; case MOtionEvent.ACTION_MOVE: if(父容器需要此类点击事件){ parent.requestDisallowInterceptTouchEvent(false); } break; } return super.dispatchTouchEvent(event); }
- 自定义View基础(二)事件分发机制
- Android自定义View总结(二)事件分发机制
- Android自定义View的事件分发机制(二)
- 自定义View的事件分发机制
- 自定义View的事件分发机制
- 自定义View的事件分发机制
- View的事件分发机制二--事件分发规则
- Android View、ViewGroup 事件分发机制(二)
- View 触摸事件分发拦截机制(二)
- View事件分发机制(二)
- Android----View事件分发机制(二)
- 自定义View(二)--表层浅析View的事件分发机制和滑动冲突
- view 事件分发机制
- View 事件分发机制
- View事件分发机制
- view事件分发机制
- View事件分发机制
- view事件分发机制
- for(foo('A');foo('B')&&(i<2);foo('C')) ,其实考的就是for (初始化语句; 判断条件; 循环条件)
- 12.java中是否有goto语句
- 2.1详解变量的定义、初始化与赋值
- Java线程简单调用
- 面向对象B/S有关JavaSE总结
- 自定义View基础(二)事件分发机制
- zoj1858
- Android 带删除按钮的EdiText
- 泛型用法
- day08--运算符、流程控制
- VTK修炼之道16:图像处理_窗口分割和图像融合(Viewport&vtkImageBlend)
- 广度优先算法(BFS)
- windows10产品密钥分享
- morphia与spring的整合