您的位置:首页 > 移动开发 > Android开发

Android 事件分发机制

2016-07-28 18:07 447 查看
http://blog.csdn.net/mackkill/article/details/50923717

 


Android 事件分发机制

标签: android经验
2016-03-18 15:51 490人阅读 评论(0) 收藏 举报


 分类:
 

学习经验(12) 


版权声明:本文为博主原创文章,未经博主允许不得转载。

在写自定义控件或者view的时候肯定会涉及到事件的分发,今天来记录下自己的学习经验。
首先我们要知道跟touch事件有关的方法有:
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">dispatchTouchEvent</span>(MotionEvent ev);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onInterceptTouchEvent</span>(MotionEvent ev);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onTouchEvent</span>(MotionEvent ev); </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

dispatchTouchEvent() 

用来分派事件。其中调用了onInterceptTouchEvent()和onTouchEvent(),一般不重写该方法。
onInterceptTouchEvent() 

用来拦截事件。默认是:{return false;}表示不拦截该事件,事件将向下传递。若重写该方法,使其返回true,则表示拦截事件终止向下传递
onTouchEvent() 

用来处理事件。返回true则表示该View能处理该事件,事件将被消费掉;返回false表示不能处理,则把事件继续向下分发,如果向下没有子view则向上返回上一级处理,以此类推继续返。
这里还有个 
public boolean onTouch(View v, MotionEvent event)
 方法要说明下:
onTouchEvent(MotionEvent ev)
 和 
onTouch(View
v, MotionEvent event)
 都可以用来处理手势监听,他们的区别我们通过两个例子来了解: 

1、
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">MyButton</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Button</span> {</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">MyButton</span>(Context context) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// TODO Auto-generated constructor stub  </span>
}

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">MyButton</span>(Context context, AttributeSet attributeSet) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(context, attributeSet);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// TODO Auto-generated constructor stub  </span>
}

<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onTouchEvent</span>(MotionEvent event) {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.onTouchEvent(event); ;
} </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>

2、
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">MyButton= (Button) findViewById(R.id.mybutton);
MyButton.setOnTouchListener(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> OnTouchListener() {

<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">onTouch</span>(View v, MotionEvent event) {
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// TODO Auto-generated method stub</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
}
});</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

可以看到一个是在重写控件的时候重写的方法,一个是在Activity里面设置监听时调用的方法。 

但是onTouchListener的onTouch方法优先级比onTouchEvent高,如果都设置的话onTouch会先触发。 

假如onTouch方法返回false会接着触发onTouchEvent,反之如果返回true则onTouchEvent方法不会被调用。 

诸如onclick事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。 

他俩都可以监听手势操作。由于平时我们一般都会比较偏向重写onTouchEvent方法。所以这里就只拿onTouchEvent来说。
好了言归正传接着说上述三个方法,上述三个方法不同的类拥有的方法也不同: 

1、Activity类拥有: 
dispatchTouchEvent(); onTouchEvent();
 

2、ViewGroup(继承自View,表示可以有子控件,如FrameLayout、Linearlayout、Listview这些): 三个方法都拥有。 

3、View(普通的控件,没有子布局的,如Button、TextView): 
dispatchTouchEvent(); onTouchEvent();

现在用一个例子来具体说下过程: 



A –> frameLayout 

C –> LinearLayout 

D –> TextView
现在开始点击D 

图是自带的画图工具画的,希望大家凑合看下。。。 



总得来说,当点击事件到底层View(一般是个ViewGroup)以后,就会调用这个ViewGroup的dispatchTouchEvent方法,如果这个ViewGroup拦截事件返回true(默认是返回false),则事件由此ViewGroup处理,如果此时ViewGroup的OnTouchListener被设置,则onTouch会被调用,否则onTouchEvent会被调用,如果都提供的话就是上面所说的onTouch优先级高会屏蔽掉onTouchEvent。反之如果ViewGroup的拦截事件返回false,则事件会传递给在他点击链上的子View,这个时候子View的dispatchTouchEvent被调用,到此为止事件就从底层View传递到它的上一层View了,接下来的和其底层View传过来的行为一致了,如此循环直到整个事件派发结束。如果一个点击事件的子View的onTouchEvent返回了false,其父的onTouchEvent也返回了false,所有的View都没去处理,则最终会由Activity来处理。
如果你看过我自定义view-SlideSwitch开源详解的就会发现
public
boolean onTouchEvent(MotionEvent event)
 方法里面的第一句话
getParent().requestDisallowInterceptTouchEvent(true);
 这句话出现的原因是当SlideSwitch放在ScrollView里面滑动的时候会和ScrollView的滑动产生冲突,所以这里我们需要在按住SlideSwitch滑动的时候屏蔽掉ScrollView的滑动。通过requestDisallowInterceptTouchEvent()我们可以对disallowIntercept的值进行修改。这里为什么这么修改,大家有兴趣可以查看下源码,这里就不给提供了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: