android 事件处理
用到的例子工程介绍:在viewGroup中加入子view,即LinerLayout中存在一子view,在MyLinerLayout中重写了 dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent
在MyTestView中重写了dispatchTouchEvent、onTouchEvent。
分别研究各种返回值对事件传递的路径影响。
MyLinerLayout.java
- public class MyLinearLayout extends LinearLayout implements View.OnClickListener,View.OnLongClickListener {
- private final static String TAG = "TouchEvent";
- public MyLinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- Log.v(TAG , "MyLinearLayout");
- //this.setOnClickListener(this);
- //this.setOnLongClickListener(this);
- }
- public void onClick(View v) {
- // TODO Auto-generated method stub
- Log.v(TAG , "MyLinearLayout onClick [" + "] test.................view:"+v.getId() );
- }
- @Override
- public boolean onLongClick(View v) {
- // TODO Auto-generated method stub
- boolean b = true;
- Log.v(TAG , "MyLinearLayout onLongClick [" + "] test.................view:"+v.getId() +"return :"+b);
- return true;
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_MOVE");
- return false;
- //break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "MyLinearLayout --dispatchTouchEvent action:ACTION_CANCEL");
- break;
- }
- // Log.v(TAG , "dispatchTouchEvent "+super.dispatchTouchEvent(ev));
- boolean b = super.dispatchTouchEvent(ev);
- //boolean b = false;
- Log.v(TAG , "MyLinearLayout --dispatchTouchEvent ["+action+ "] test.................return:"+b);
- return b;
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "MyLinearLayout --onInterceptTouchEvent action:ACTION_CANCEL");
- break;
- }
- //boolean b = super.onInterceptTouchEvent(ev);
- boolean b = true;
- Log.v(TAG , "MyLinearLayout --onInterceptTouchEvent ["+action+ "] test.................return: "+b);
- return b;
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- //boolean b = super.onTouchEvent(ev);
- boolean b = true;
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "MyLinearLayout---onTouchEvent action:ACTION_CANCEL");
- break;
- }
- Log.v(TAG , "MyLinearLayout --onTouchEvent ["+action+ "] test.................return: "+b);
- return b;
- }
- }
- TextView.java
- package com.lee.stony;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.widget.SimpleAdapter.ViewBinder;
- import android.widget.TextView;
- import android.view.View;
- public class MyTestView extends TextView{
- public static final String TAG = "TouchEvent";
- public MyTestView(Context context, AttributeSet attrs) {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- Log.v(TAG, "MyTestView");
- /*this.setOnClickListener(this);
- this.setOnLongClickListener(this);*/
- }
- /*@Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- Log.v(TAG , "MyTestView onClick [" + "] test.................view:"+v.getId() );
- }
- @Override
- public boolean onLongClick(View v) {
- // TODO Auto-generated method stub
- boolean b = true;
- Log.v(TAG , "MyTestView onLongClick [" + "] test.................view:"+v.getId() +"return :"+b);
- return true;
- }
- */
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "MyTestView-- dispatchTouchEvent action:ACTION_CANCEL");
- break;
- }
- boolean b = super.dispatchTouchEvent(ev);
- //boolean b = true;
- Log.v(TAG , "MyTestView dispatchTouchEvent ["+action+ "] test.................return:"+b);
- return b;
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean b = super.onTouchEvent(ev);
- int action = ev.getAction();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_DOWN");
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_MOVE");
- break;
- case MotionEvent.ACTION_UP:
- Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_UP");
- break;
- case MotionEvent.ACTION_CANCEL:
- Log.d(TAG, "MyTestView-- ---onTouchEvent action:ACTION_CANCEL");
- break;
- }
- //boolean b = true;
- Log.v(TAG , "MyTestView onTouchEvent ["+action+ "] test.................return:"+b);
- return b;
- }
- }
1、 android中用于事件处理的方法和类主要有如下几种:
onTouchEvent
onInterceptTouchEvent//在viewgroup才有的方法,用于分发子view
dispatchTouchEvent
实现View.OnClickListener 的onClick
实现View.OnLongClickListener 的 onLongClick
实现View.OnTouchClickListener 的 onTouch
说明:在事件处理中,其实我们一般遇到事件有3中,分别是down、move、up,其中move事件在一个操作中(这里说的一个操作就是用户与屏幕的交互,即由down到up的动作序列)可能会发生多次,但是,我们认为一个动作序列会包含以上三种事件,因此,在事件处理中就是要处理好这个过程,而最重要的就是down事件,这是一个动作序列的起始,没有down谈不上后面的事件了。所以,我们把消耗down事件的类当做是这个动作序列的最终载体。
2、 各种返回值的含义和作用
(1)dispatchTouchEvent()
返回值 |
作用 |
True |
继续接受动作序列中的后续事件,如move、move、up |
False |
不接受动作序列中的后续事件,因此本次后续操作不起作用,如:down后返回false,则move和up都不会被接受,只能接受下个动作。这里为什么特别指定的down事件呢,因为如果down返回true,说明后续事件会被传递于此,但是move返回false呢?哈哈,这个就不会影响了,因此说down才是关键 |
总结:此方法一般用于初步处理事件,因为动作是由此分发,所以通常会调用super.dispatchTouchEvent。这样就会继续调用onInterceptTouchEvent,再由onInterceptTouchEvent决定事件流向。
例子:
当在DispatchTouchEvent中调用了super.dispatchTouchEvent,则会继续向下执行到onInterceptTouchEvent方法。
(2)onInterceptTouchEvent():
返回值 |
作用 |
True |
事件会传递到自己的onTouchEvent() |
False |
传递到下一个view的dispatchTouchEvent() |
例子1:
类 |
方法 |
返回值 |
说明 |
MyLinerLayout |
dispatchTouchEvent |
True |
调用super. dispatchTouchEvent |
onInterceptTouchEvent |
true |
True 则调用自己的onTouchEvent |
|
onTouchEvent |
true |
True 则后续动作序列直接发到此处,不经过onInterceptTouchEvent |
|
MyTestView |
dispatchTouchEvent |
True |
这里因为MyLinerLayout. onInterceptTouchEvent返回true,因此不会传递于此 |
onTouchEvent |
True |
|
图:点击父和子view效果一样
说明:Down事件在MyLinerLayout.onInterceptTouchEvent()后返回true,则传递到onTouchEvent,当其返回true时,动作序列的后续事件不会再通过onInterceptTouchEvent了,而是在dispatchTouchEvent中直接传递于onTouchEvent。注意:此处点击MylinerLayout和MytestView效果一致。
例子2:
类 |
方法 |
返回值 |
说明 |
MyLinerLayout |
dispatchTouchEvent |
True |
调用super. dispatchTouchEvent |
onInterceptTouchEvent |
False |
False则点击非子view(没有子view处理)时会传递于onTouchEvent,但是如果点击MyTestView,即它的子view,则会传递到子view的onDispatchTouchEvent |
|
onTouchEvent |
true |
True 则后续动作序列直接发到此处,不经过onInterceptTouchEvent |
|
MyTestView |
dispatchTouchEvent |
True |
调用super. dispatchTouchEvent |
onTouchEvent |
True |
|
图1:点击父view
说明:onInterceptTouchEvent返回false本应该传给下个子view的dispatchTouchEvent,但是,点击的是父view,因此不存在子view而直接传给自己的onTouchEvent,并且onTouchevent返回true,所以,后续事件不经过onInterceptTouchEvent(确定了自己要处理就不必再考虑如何分发给子view了)
图2:点击子view
说明:可以看到虽然MytestView.onTouchEvent接受并返回了true,事件还是需要经过MyLinerLayout.onInterceptTouchEvent(这是一个通道,分发给子view就要经过),
总结:onInterceptTouchEvent要做的就是确定事件传递到哪个子view,如果返回false,但是又没有子view处理(因为根本就没有点击到子view),就自己处理了,而自己在onTouchEvent处理的后续事件就不必经过onInterceptTouchEvent了,它是判断传递给子view的,都不是子view处理,就不用经过了。(以上说明,android事件处理机制中,明确谁要处理,确定后就会形成一条通道,后续事件就走这条通道吧)
注意:正常情况下dispatchTouchEvent会调用super. dispatchTouchEvent,并将其作为返回值,其实这会传递下一个接受者,让下个接受者处理并将最终的处理的返回值(在最后的onTouchEvent中,让其决定是否还需要接受后续动作序列)作为自己的返回值。而下个调用者即是onInterceptTouchEvent,不过它只是决定分发方向的,所以它的返回值对dispatchTouchEvent不影响,而onInterceptTouchEvent也可以调用super. onInterceptTouchEvent,但是这总返回false,即总希望让子view来处理。一般不用
(2)onTouchEvent():
返回值 |
作用 |
True |
事件由自己处理消耗,后续动作序列让其处理,因为在down事件时确定了路径,因此后续事件就不会迷路了 |
False |
自己不消耗事件了,向上返回让其他来父view的onTouchEvent接受处理吧 |
例子3:
类 |
方法 |
返回值 |
说明 |
MyLinerLayout |
dispatchTouchEvent |
|
调用super. dispatchTouchEvent,根据不同的view的返回值会不同,不过此处总是返回false |
onInterceptTouchEvent |
False |
False则点击非子view(没有子view处理)时会传递于onTouchEvent,但是如果点击MyTestView,即它的子view,则会传递到子view的onDispatchTouchEvent |
|
onTouchEvent |
False |
False 则后续动作序列一般不发到此处(要看dispatchTouchEvent的返回值,如果其使用super. dispatchTouchEvent,会使用本方法的返回值,即false)。 |
|
MyTestView |
dispatchTouchEvent |
|
调用super. dispatchTouchEvent,也会返回false |
onTouchEvent |
False |
|
图1:点击父view
说明:当传递到自己的onTouchEvent时,返回false,而dispatchTouchEvent也使用这返回值false,因此,本次操作的后续动作序列就不会再传递了,没有view处理后续的move、up。除非再次点击才会有事件传递,不过,结果跟上图一样,处理了down返回false就没下文了。
图2:点击子view
说明:当事件流向MytestView.onTouchEvent时,返回了false,说明自己不处理了,让父view的onTouchEvent处理吧,而父view也返回false不处理,就继续向上抛,直到消失,当down事件没有被view确认处理,则后续动作序列也就不会再传递了。
例子4:跟例子3差不多,只是MyLinerLayout.onTouchEvent返回true
类 |
方法 |
返回值 |
说明 |
MyLinerLayout |
dispatchTouchEvent |
|
调用super. dispatchTouchEvent,根据不同的view的返回值会不同,不过此处总是返回false |
onInterceptTouchEvent |
False |
False则点击非子view(没有子view处理)时会传递于onTouchEvent,但是如果点击MyTestView,即它的子view,则会传递到子view的onDispatchTouchEvent |
|
onTouchEvent |
True |
True 则后续动作序列直接发到此处,不经过onInterceptTouchEvent |
|
MyTestView |
dispatchTouchEvent |
|
调用super. dispatchTouchEvent,也会返回false |
onTouchEvent |
False |
事件没有被消耗,传给父view的onTouchEvent |
注意:这里点击父view会跟例子2中图1一样,因为,事件根本没有传递到子view的机会。
图1:点击子view
说明:当到达MyTestView. onTouchEvent时返回false,则传递给父view的onTouchEvent,而其返回true,说明就让其处理吧,所以后续动作序列直接发到此处。
总结:onTouchEvent被认为是动作的最终处理的函数,不管是父view还是子view处理,只要onTouchEvent消耗了事件(返回true),则认为后续动作序列的通路已经确定,否则,向上处理,直到消失。
相关推荐
Android事件处理机制
Android事件处理
Android事件处理系统允许应用程序响应用户的触摸、键盘输入、网络变化等各种事件。本篇将详细解析Android事件处理机制,特别是基于给定的"android 事件处理demo",我们将深入探讨如何在实际应用中处理触摸事件。 ...
Android事件处理机制是Android应用程序开发中的关键组成部分,它使得用户与应用之间能够进行有效的交互。在Android系统中,事件处理主要包括触摸事件、键盘事件、广播事件等,这些事件的处理方式直接影响到应用的...
在Android应用开发中,事件处理机制是至关重要的组成部分,它涉及到用户与应用程序的交互,包括点击、滑动等各类操作。本示例"Android 事件处理机制 demo"将深入探讨这一主题,通过实际代码演示如何有效地管理和响应...
长期更新的Android事件处理教程应该会涵盖以上各个知识点,并随着Android版本的更新,介绍新的API和最佳实践。例如,Android Jetpack中的`ViewBinding`简化了视图引用,`MotionEvent`提供了更精细的触摸事件处理,...
下面将详细阐述Android事件处理的相关知识点。 1. **事件传递机制** Android事件传递遵循"事件冒泡"原理,即事件会先由最底层的视图接收,如果该视图不处理,则事件会向上逐层传递,直到被某个视图处理或到达根...
在Android开发中,键盘事件处理是一项重要的技能,它涉及到用户输入的交互逻辑,对提升应用的用户体验至关重要。本文将深入探讨Android键盘事件处理,并通过一个实际的案例来讲解相关知识点。 首先,Android中的...
Android事件处理,触摸事件、监听事件、手势识别等技术颇有研究,对个人开发非常有用。请安心下载。
首先,Android事件处理主要围绕Input子系统进行,它包含了键盘、触摸屏等设备输入的管理和分发。InputManager是这一子系统的核心,它在Java层和C++层都有相应的实现。在Java层,WindowManagerService创建Input...
通过这个demo,开发者可以直观地了解Android事件处理机制,并进行实际操作以验证其工作原理。这对于优化用户界面交互和调试事件处理问题具有重要的实践意义。在实际开发中,灵活运用事件派发机制可以创建更高效、...
(1)理解Android的应用组件及其功能、特点 ...(3)理解并掌握Android的事件处理机制,掌握基于监听的事件处理机制和基于回调的事件处理机制使用方法 (4)了解Android的对话框与消息框,掌握Android的Toast。