1.Android的事件处理机制 (1)基于监听的事件处理方式 通常做法是为Android界面组件绑定特定的事件监听器,在事件监听器的方法里编写事件处理代码。 (2)基于回调的事件处理方式 通常做法是重写Android组件的特定的回调方法,Android为绝大部分界面组件都提供了事件相应的回调方法,我们只需重写它们即可。当我们触发相应组件时,由系统根据具体情景自动调用组件的方法。 (3)直接绑定到标签 即我们在界面布局文件中为指定组件标签设置事件属性,属性值是一个方法的方法名,然后再在Activity中定义该方法,编写具体的事件处理代码,当我们触发绑定android:OnClick标签的组件时,作出相应的响应。 2.Android消息传递机制 (1)Handler消息传递 (2)异步任务处理。 二、基于监听的事件处理 1.事件处理模型 基于监听的事件处理模型,主要涉及三类对象: (1)EventSource(事件源) 产生事件的组件,即事件发生的场所,如按钮、菜单等; (2)Event(事件) 具体某一操作的详细描述,事件封装了操作的相关信息,如果想获得事件源上所发生事件的相关信息,可通过Event对象来取得,例如按键事件按下的是哪个键、触摸事件发生的位置等; (3)EventListener(事件监听器) 负责监听用户在事件源上的操作(如单击),并对用户的各种操作做出相应的相应,事件监听器中可包含多个事件处理器,一个事件处理器实际上就是一个事件处理方法。 说明:实际上,基于监听的事件处理是一种委托式事件处理。普通组件(事件源)将整个事件处理委托给特定的对象(事件监听器),当该事件源发生指定的事情时,系统自动生成事件对象,并通知所委托的事件监听器,由事件监听器相应的事件处理器来处理这个事件。 2.基于监听的事件处理开发步骤 (1)获取普通界面控件(事件源),即被监听的对象; (2)实现事件监听器类,该监听器类是一个特殊的Java类,必须实现一个XxxListener接口。需要注意的是,实现事件监听器主要有四种形式: >内部类形式:将事件监听器类定义为当前类的内部类; >外部类形式:将事件监听器类定义成一个外部类; >类自身作为事件监听器类:让Activity本身实现监听器接口,并实现事件处理方法; >匿名内部类:使用匿名内部类创建事件监听器对象; (3)调用事件源的setXxxListener方法将事件监听器对象将事件监听器对象作为传入参数注册给普通组件(事件源)。 三、简易文本编辑器实例 通过该例,我们将学习如何使用内部类形式等四种方式来实现事件监听器。 1.源码 (1)EventTest1.java:主Activity代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
package
com.example.androidevent;
import
android.app.Activity;
import
android.graphics.Color;
import
android.graphics.Typeface;
import
android.os.Bundle;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.Button;
import
android.widget.EditText;
import
android.widget.TextView;
public
class
EventTest1
extends
Activity
implements
OnClickListener
{
private
TextView content;
int
flag=
0
;
//字体样式标识
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
content = (TextView)findViewById(R.id.content);
//1.颜色:内部类形式
Button redBtn = (Button)findViewById(R.id.red);
Button greenBtn = (Button)findViewById(R.id.green);
Button blueBtn = (Button)findViewById(R.id.blue);
EventListener inner =
new
EventListener();
//实例化一个事件监听器对象
redBtn.setOnClickListener(inner);
//向以下界面组件注册同一个事件监听器
greenBtn.setOnClickListener(inner);
blueBtn.setOnClickListener(inner);
//2.字体大小:外部类形式
Button bigger = (Button)findViewById(R.id.big);
Button smaller = (Button)findViewById(R.id.small);
OuterListener outer =
new
OuterListener(content);
//实例化一个事件监听器对象
bigger.setOnClickListener(outer);
smaller.setOnClickListener(outer);
//3.字体样式:类自身作为事件监听器
Button boldBtn = (Button)findViewById(R.id.bold);
Button inclineBtn = (Button)findViewById(R.id.incline);
Button normalBtn = (Button)findViewById(R.id.normal);
boldBtn.setOnClickListener(
this
);
//向以下界面组件注册同一个事件监听器
inclineBtn.setOnClickListener(
this
);
normalBtn.setOnClickListener(
this
);
//4.匿名内部类
final
EditText text = (EditText)findViewById(R.id.text);
text.setOnClickListener(
new
OnClickListener(){
public
void
onClick(View v)
{
String contentText=text.getText().toString();
content.setText(contentText);
//将编辑框内容设置到文本显示框中
}
});
}
/*方法一:内部类形式
* 在onClick函数中,通过视图的getId()方法判定产生事件组件的ID并作出相应的响应*/
public
class
EventListener
implements
OnClickListener
{
public
void
onClick(View arg0) {
switch
(arg0.getId())
{
case
R.id.red:
//设置红色按钮被按下
content.setTextColor(Color.RED);
break
;
case
R.id.green:
content.setTextColor(Color.GREEN);
break
;
case
R.id.blue:
content.setTextColor(Color.BLUE);
break
;
default
:
break
;
}
}
}
/*方法3.类自身作为事件监听器*/
@Override
public
void
onClick(View v)
{
//flag为样式标识,当flag=0表示默认,flag=1表示倾斜,flag=2表示加粗,flag=3表示倾斜又加粗
switch
(v.getId())
{
case
R.id.bold:
//设置加粗
if
(flag==
1
||flag==
3
)
{
content.setTypeface(Typeface.MONOSPACE,Typeface.BOLD_ITALIC);
//设置系统默认的字体样式
flag=
3
;
}
else
{
content.setTypeface(Typeface.MONOSPACE,Typeface.BOLD);
flag=
2
;
}
break
;
case
R.id.incline:
if
(flag==
2
|| flag==
3
)
{
content.setTypeface(Typeface.MONOSPACE,Typeface.BOLD_ITALIC);
//设置系统默认的字体样式
flag=
3
;
}
else
{
content.setTypeface(Typeface.MONOSPACE,Typeface.ITALIC);
flag=
1
;
}
break
;
case
R.id.normal:
content.setTypeface(Typeface.MONOSPACE,Typeface.NORMAL);
//设置系统默认的字体样式
flag=
0
;
break
;
default
:
break
;
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package
com.example.androidevent;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.TextView;
/*外部类形式*/
public
class
OuterListener
implements
OnClickListener
{
private
TextView text;
private
float
size;
//构造方法1:将文本组件对象作为参数传递并赋值给类成员对象
public
OuterListener(TextView t)
{
this
.text = t;
}
//构造方法2
public
OuterListener()
{
super
();
}
public
void
onClick(View v)
{
size= text.getTextSize();
//获取文本字体大小
switch
(v.getId())
{
case
R.id.big :
{
size+=
4
;
break
;
}
case
R.id.small :
{
size-=
4
;
break
;
}
default
:
break
;
}
//设置最值限度
if
(size<=
8
)
size=
8
;
if
(size>=
72
)
size=
72
;
text.setTextSize(size);
}
}
|
(2)效果演示
(3)源码分析 a.内部类形式:即将事件监听器类定义为当前类的内部类。 >优势:一是使用内部类可以在当前类中复用该监听器类,即多个事件源可以注册同一个监听器; 二是使用内部类可以自由访问外部类的所有界面控件,内部类实质上是外部类的成员。 >适用范围:内部类形式比较适合于多个事件源同时注册同一事件监听器的情形。 b.外部类形式:将事件监听器类定义成一个外部类; >缺点:一是由于事件监听器通常属于特定的GUI,定义成外部类不利于提高程序的内聚性(如例子中需要通过外部类的构造方法传递一个文本对象并将其赋值给当前类的文本对象成员才能对其进行操作);二是外部类形式的事件监听器不能自由访问创建GUI界面中的组件且 编程 不够简洁。 >使用范围:如果某个事件监听器确实需要被多个GUI界面所共享,而且主要是完成某种业务逻辑的实现,则可以考虑使用外部类的形式来定义事件监听器类。 c.类自身作为事件监听器类:让Activity本身实现监听器接口,并实现事件处理方法; >优点:Activity类本身作为事件监听器,就如同生活中,我们自己刚好能够处理某一件事,不需要委托给他人处理,可以直接在Activity类中定义事件处理器方法,这种形式非常简洁。 >缺点:可能造成程序结构混乱,Activity的主要职责应该是完成界面初始化工作,但此时还需包含事件处理器方法,从而引起混乱; 如果Activity界面类需要实现监听器接口,给人感觉比较怪异。 d.匿名内部类:使用匿名内部类创建事件监听器对象 >优点:事件处理器都没有什么复用价值(可复用代码通常都被抽象成了业务逻辑方法),因此大部分事件监听器只是临时使用一次,所以使用匿名内部类形式的事件监听器更合适。实际上,这种形式也是目前使用最广泛的事件监听器形式。注意:是匿名内部类中访问局部成员变量时,该成员变量必须是final修饰的,而对于成员变量则没有这个要求。 四、常见事件监听器接口及其处理方法 以上四种形式都需要通过事件监听类的OnClick成员处理方法,根据界面 组件 的Id来提供事件响应。此外,除匿名内部类形式,其余三种都需要类继承相应的事件监听器接口。 1.常见事件监听器接口及处理方法
事件 | 接口 | 处理方法 | 描述 |
单击事件 | View.OnClickListener | abstract void onClick (View v) | 单击组件时触发 |
单击事件 | View.OnLongClickListener | abstract boolean onLongClick (View v) | 长按组件时触发 |
键盘事件 | View.OnKeyListener | abstract boolean onKey(View v, int keyCode, KeyEvent event) | 处理键盘事件 |
焦点事件 | View.OnFocusChangeListener | abstract void onFocusChange (View v, boolean hasFocus) | 当焦点发生改变时触发 |
触摸事件 | View.OnTouchListener | abstract boolean onTouch (View v, MotionEvent event) | 产生触摸事件 |
方法 | 描述 |
void setOnClickListener(View.OnClickListener l) | 注册单击事件 |
void setOnLongClickListener(View.OnLongClickListener l) | 注册长按事件 |
void setOnKeyListener(View.OnKeyListener l) | 注册键盘事件 |
void setOnFocusChangeListener(View.OnFocusChangeListener l) | 注册焦点改变事件 |
void setOnTouchListener(View.OnTouchListener l) | 注册触摸事件 |
void setOnCreateContextMenuListener(View.OnCreateContextMenuListener l) |