Android键盘和触摸事件先后顺序处理

activity和VIEW都能接收触摸和按键,如果响应事件只需要在继承类里复写事件函数即可

但是对于VIEW来说,我们如果不改变DRAW,不需要继承,所以如果想响应事件,则需要

当一个视图(如一个按钮)被触摸时,该对象上的 onTouchEvent() 方法会被调用。不过,为了侦听这个事件,你必须扩展这个类并重写该方法。很明显,扩展每个你想使用的视图对象(只是处理一个事件)是荒唐的。这就是为什么视图类也包含了一个嵌套接口的集合,这些接口含有实现起来简单得多的回调函数。这些接口叫做事件侦听器 event listeners ,是用来截获用户和你的界面交互动作的“门票”。

 1.只有一个ACTIVITY得情况:

    当鼠标键按下时(即触摸)

   首先触发dispatchTouchEvent

   然后触发onUserInteraction

   再次onTouchEvent

   如果是点击的话,紧跟着下列事件(点击分俩步,ACTION_DOWN,ACTION_up)

  触发dispatchTouchEvent

  再次onTouchEvent

  当ACTION_up事件时不会触发onUserInteraction(可查看源代码)

  当键盘按下时

 首先触发dispatchKeyEvent

 然后触发onUserInteraction

 再次onKeyDown

 如果按下紧接着松开,则是俩步

 紧跟着触发dispatchKeyEvent

 然后触发onUserInteraction

 再次onKeyUp

 注意与触摸不同,当松开按键时onUserInteraction也会触发。

   Activity.dispatchTouchEvent(MotionEvent) - 这允许你的活动可以在分发给窗口之前捕获所有的触摸事件。

(同理 dispatchKeyEvent)

onUserInteraction :Called whenever a key, touch, or trackball event is dispatched to the
     * activity.

2.activity里有一个LAYOUT,在布局里有个按钮。

如果在按钮上触发一个CLICK事件

首先触发ACTIVITY的dispatchTouchEvent

然后触发ACTIVITY的onUserInteraction

然后触发LAYOUT的dispatchTouchEvent

然后触发LAYOUT的onInterceptTouchEvent

然后触发BUTTON的onTouch(这是一个ACTION_DOWN事件)

紧跟着是一个ACTION_UP事件

触发ACTIVITY的dispatchTouchEvent

注意不再触发ACTIVITY的onUserInteraction,因为他对ACTION_UP不起作用。

然后触发LAYOUT的dispatchTouchEvent

然后触发LAYOUT的onInterceptTouchEvent

然后触发BUTTON的onTouch

最后触发BUTTON的onClick.

如果你在ONTOUCH事件里返回true,消费了此事件,那么ONCLICK将不会被响应

但是如果你不写ONCLICK事件,而ONTOUCH事件返回FLASE

那么最终事件序列:

11-23 17:19:44.313: INFO/activity(803): dispatchTouchEvent
11-23 17:19:44.313: INFO/activity(803): onUserInteraction
11-23 17:19:44.322: INFO/LinearLayout(803): dispatchTouchEvent
11-23 17:19:44.333: INFO/LinearLayout(803): onInterceptTouchEvent
11-23 17:19:44.341: INFO/button(803): onTouch 
11-23 17:19:44.441: INFO/activity(803): dispatchTouchEvent
11-23 17:19:44.451: INFO/LinearLayout(803): dispatchTouchEvent
11-23 17:19:44.451: INFO/LinearLayout(803): onInterceptTouchEvent
11-23 17:19:44.461: INFO/button(803): onTouch

即事件不会再向上传递,估计是ONCLICK有默认响应不处理,而ONCLICK不会有返回值。

但是如果是继承了一个VIEW而且又覆写了onTouchEvent,他返回FALSE

当触摸事件发生时

11-23 17:25:59.691: INFO/activity(831): dispatchTouchEvent
11-23 17:25:59.691: INFO/activity(831): onUserInteraction
11-23 17:25:59.701: INFO/LinearLayout(831): dispatchTouchEvent
11-23 17:25:59.701: INFO/LinearLayout(831): onInterceptTouchEvent
11-23 17:25:59.701: INFO/button(831): onTouch 
11-23 17:25:59.701: INFO/Button(831): onTouchEvent
11-23 17:25:59.701: INFO/LinearLayout(831): onTouchEvent
11-23 17:25:59.701: INFO/activity(831): onTouchEvent
11-23 17:25:59.822: INFO/activity(831): dispatchTouchEvent
11-23 17:25:59.822: INFO/activity(831): onTouchEvent

奇怪的是,ONCLICK事件不再发生。

VIEW和ACTIVITY本身都有相应键盘事件的ONKEYUP和ONKEYDOWN

对于VIEW来说,你可以setOnKeyListener(new OnKeyListener(){
            @Override
            public boolean onKey(

来响应键盘事件,如果你既对VIEW写了这个侦听,又覆写了ONKEYUP,DOWN事件,那么首先

进入ONKEY

比如用反向键把焦点切换到按钮上

事件序列:

11-23 17:23:14.392: INFO/activity(803): dispatchKeyEvent
11-23 17:23:14.404: INFO/activity(803): onUserInteraction
11-23 17:23:14.412: INFO/LinearLayout(803): dispatchKeyEvent
11-23 17:23:14.412: INFO/button(803): onKey
11-23 17:23:14.422: INFO/activity(803): onKeyUp

当按回车时

11-23 17:35:55.692: INFO/activity(831): dispatchKeyEvent
11-23 17:35:55.713: INFO/activity(831): onUserInteraction
11-23 17:35:55.722: INFO/LinearLayout(831): dispatchKeyEvent
11-23 17:35:55.732: INFO/button(831): onKey
11-23 17:35:55.813: INFO/activity(831): dispatchKeyEvent
11-23 17:35:55.824: INFO/activity(831): onUserInteraction
11-23 17:35:55.831: INFO/LinearLayout(831): dispatchKeyEvent
11-23 17:35:55.831: INFO/button(831): onKey
11-23 17:35:55.953: INFO/button(831): onClick

最后补充下:不需要那么复杂,如果对于控件想响应他的触摸事件,如果继承

则覆写ONTOUCHEVENT,如果不覆写则侦听ONTOUCH

如果覆写了ONTOUCHEVENT,则不再响应ONCLICK事件

如果写了ONCLICK,则不要再搞ONTOUCHEVENT了

所以ONCLICK和ONTOUCHEVENT二取一,另外如果有ONTOUCH侦听,那么此函数要先于其他函数执行

对于ONCLICK来说,要从头走俩便ONTOUCH,一次是DOWN,一次是UP

同样的对于ONKEY,以及ONKEYUP和DOWN

如果既覆写了ONKEYUODOWN,又SET了侦听ONKEY,那么ONKEY要优先执行,对于一个回车按键触发时

11-24 09:55:18.601: INFO/activity(951): dispatchKeyEvent
11-24 09:55:18.611: INFO/activity(951): onUserInteraction
11-24 09:55:18.621: INFO/LinearLayout(951): dispatchKeyEvent
11-24 09:55:18.641: INFO/button(951): onKey
11-24 09:55:18.711: INFO/activity(951): dispatchKeyEvent
11-24 09:55:18.756: INFO/activity(951): onUserInteraction
11-24 09:55:18.775: INFO/LinearLayout(951): dispatchKeyEvent
11-24 09:55:18.791: INFO/button(951): onKey
11-24 09:55:18.822: INFO/button(951): onClick


*****************************************************************************************************************************************************************************************

onTouchEvent的处理顺序

由于onInterceptTouchEvent()的机制比较复杂,总结一下,基本的规则是: 
1.       down事件首先会传递到onInterceptTouchEvent()方法 
2.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后returnfalse,那么后续的move,up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。 
3.       如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后returntrue,那么后续的move,up等事件将不再传递给onInterceptTouchEvent(),而是和down事件一样传递给该ViewGroup的onTouchEvent()处理,注意,目标view将接收不到任何事件。 
4.       如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。 
5.       如果最终需要处理事件的view的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。 

下面用一个简单的实验说明上述复杂的规则。视图自底向上共3层,其中LayoutView1和LayoutView2就是LinearLayout,MyTextView就是TextView: 
对应的xml布局文件如下: 
<?xml version="1.0"encoding="utf-8"?> 
<com.touchstudy.LayoutView1xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <com.touchstudy.LayoutView2 
        android:orientation="vertical" 
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:gravity="center"> 
        <com.touchstudy.MyTextView 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:id="@+id/tv" 
            android:text="AB" 
            android:textSize="40sp" 
            android:textStyle="bold" 
            android:background="#FFFFFF" 
            android:textColor="#0000FF"/> 
    </com.touchstudy.LayoutView2> 
</com.touchstudy.LayoutView1> 

下面看具体情况: 
1.       onInterceptTouchEvent()处理down事件均返回false,onTouchEvent()处理事件均返回true 
------------------------------------------------------------------------------------------------------------------------------ 
04-11 03:58:42.620: DEBUG/LayoutView1(614):onInterceptTouchEvent action:ACTION_DOWN 
04-11 03:58:42.620: DEBUG/LayoutView2(614):onInterceptTouchEvent action:ACTION_DOWN 
04-11 03:58:42.620: DEBUG/MyTextView(614): onTouchEventaction:ACTION_DOWN 
04-11 03:58:42.800: DEBUG/LayoutView1(614):onInterceptTouchEvent action:ACTION_MOVE 
04-11 03:58:42.800: DEBUG/LayoutView2(614):onInterceptTouchEvent action:ACTION_MOVE 
04-11 03:58:42.800: DEBUG/MyTextView(614): onTouchEventaction:ACTION_MOVE 
…… //省略过多的ACTION_MOVE 
04-11 03:58:43.130: DEBUG/LayoutView1(614):onInterceptTouchEvent action:ACTION_UP 
04-11 03:58:43.130: DEBUG/LayoutView2(614):onInterceptTouchEvent action:ACTION_UP 
04-11 03:58:43.150: DEBUG/MyTextView(614): onTouchEventaction:ACTION_UP 
------------------------------------------------------------------------------------------------------------------------------ 
这是最常见的情况,onInterceptTouchEvent并没有做任何改变事件传递时序的操作,效果上和没有覆写该方法是一样的。可以看到,各种事件的传递本身是自底向上的,次序是:LayoutView1->LayoutView2->MyTextView。注意,在onInterceptTouchEvent均返回false时,LayoutView1和LayoutView2的onTouchEvent并不会收到事件,而是最终传递给了MyTextView。 

2.       LayoutView1的onInterceptTouchEvent()处理down事件返回true, 
MyTextView的onTouchEvent()处理事件返回true 
------------------------------------------------------------------------------------------------------------------------------ 
04-11 03:09:27.589: DEBUG/LayoutView1(446):onInterceptTouchEvent action:ACTION_DOWN 
04-11 03:09:27.589: DEBUG/LayoutView1(446): onTouchEventaction:ACTION_DOWN 
04-11 03:09:27.629: DEBUG/LayoutView1(446): onTouchEventaction:ACTION_MOVE 
04-11 03:09:27.689: DEBUG/LayoutView1(446): onTouchEventaction:ACTION_MOVE 
…… //省略过多的ACTION_MOVE 
04-11 03:09:27.959: DEBUG/LayoutView1(446): onTouchEventaction:ACTION_UP 
------------------------------------------------------------------------------------------------------------------------------ 
从Log可以看到,由于LayoutView1在拦截第一次down事件时returntrue,所以后续的事件(包括第一次的down)将由LayoutView1本身处理,事件不再传递下去。 

3.       LayoutView1,LayoutView2的onInterceptTouchEvent()处理down事件返回false, 
MyTextView的onTouchEvent()处理事件返回false 
LayoutView2的onTouchEvent()处理事件返回true 
---------------------------------------------------------------------------------------------------------------------------- 
04-11 09:50:21.147: DEBUG/LayoutView1(301):onInterceptTouchEvent action:ACTION_DOWN 
04-11 09:50:21.147: DEBUG/LayoutView2(301):onInterceptTouchEvent action:ACTION_DOWN 
04-11 09:50:21.147: DEBUG/MyTextView(301): onTouchEventaction:ACTION_DOWN 
04-11 09:50:21.147: DEBUG/LayoutView2(301): onTouchEventaction:ACTION_DOWN 
04-11 09:50:21.176: DEBUG/LayoutView1(301):onInterceptTouchEvent action:ACTION_MOVE 
04-11 09:50:21.176: DEBUG/LayoutView2(301): onTouchEventaction:ACTION_MOVE 
04-11 09:50:21.206: DEBUG/LayoutView1(301):onInterceptTouchEvent action:ACTION_MOVE 
04-11 09:50:21.217: DEBUG/LayoutView2(301): onTouchEventaction:ACTION_MOVE 
…… //省略过多的ACTION_MOVE 
04-11 09:50:21.486: DEBUG/LayoutView1(301):onInterceptTouchEvent action:ACTION_UP 
04-11 09:50:21.486: DEBUG/LayoutView2(301): onTouchEventaction:ACTION_UP 
---------------------------------------------------------------------------------------------------------------------------- 
可以看到,由于MyTextView在onTouchEvent()中returnfalse,down事件被传递给其父view,即LayoutView2的onTouchEvent()方法处理,由于在LayoutView2的onTouchEvent()中returntrue,所以down事件传递并没有上传到LayoutView1。注意,后续的move和up事件均被传递给LayoutView2的onTouchEvent()处理,而没有传递给MyTextView。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值