Android平台的事件处理机制有两种:
基于回调机制的事件处理 :Android平台中,每个View都有自己的处理事件的回调方法,开发人员可以通过重写View中的这些回调方法来实现需要的响应事件。
基于监听接口的事件处理 :面向对象设计中的主流处理方式,采用委托事件处理的方式,将发生的事件委托给注册过的事件监听器来处理.
1.基于回调机制的事件处理:重写android组件特定的一些回调方法
onKeyDown()/ onKeyUp(),该方法是接口KeyEvent.Callback中的抽象方法,所有的View全部实现了该接口并重写了该方法,该方法用来捕捉手机键盘被按下的事件。public boolean onKeyDown (int keyCode, KeyEvent event)
onTouchEvent(),该方法在View类中的定义,并且所有的View子类全部重写了该方法,应用程序可以通过该方法处理手机屏幕的触摸事件。
public boolean onTouchEvent (MotionEvent event)
onFocusChanged(),只能在View中重写。该方法是焦点改变的回调方法,当某个控件重写了该方法后,当焦点发生变化时,会自动调用该方法来处理焦点改变的事件。protected void onFocusChanged (boolean gainFocus, int direction, Rect previously FocusedRect)
2.基于监听接口的事件处理:为android组件绑定特定的事件监听器.事件监听器是视图View类的接口,包含一个单独的回调方法。这些方法将在视图中注册的监听器被用户界面操作触发时由Android框架调用。下面这些回调方法被包含在事件监听器接口中:
onClick():包含于View.OnClickListener。当用户触摸这个item(在触摸模式下),或者通过浏览键或跟踪球聚焦在这个item上,然后按下“确认”键或者按下跟踪球时被调用。
onLongClick():包含于View.OnLongClickListener。当用户触摸并控制住这个item(在触摸模式下),或者通过浏览键或跟踪球聚焦在这个item上,然后保持按下“确认”键或者按下跟踪球(一秒钟)时被调用。
onFocusChange():包含于View.OnFocusChangeListener。当用户使用浏览键或跟踪球浏览进入或离开这个item时被调用。
onKey() :包含于View.OnKeyListener。当用户聚焦在这个item上并按下或释放设备上的一个按键时被调用。
onTouch() :包含于View.OnTouchListener。当用户执行的动作被当做一个触摸事件时被调用,包括按下,释放,或者屏幕上任何的移动手势(在这个item的边界内)。
onCreateContextMenu() :包含于View.OnCreateContextMenuListener。当正在创建一个上下文菜单的时候被调用(作为持续的“长点击”动作的结果)。
Android系统界面事件的传递和处理规则
如果界面控件设置了事件监听器,则事件将先传递给事件监听器
如果界面控件没有设置事件监听器,界面事件则会直接传递给界面控件的其他事件处理函数
即使界面控件设置了事件监听器,界面事件也可以再次传递给其他事件处理函数
是否继续传递事件给其他处理函数是由事件监听器处理函数的返回值决定的
如果监听器处理函数的返回值为true,表示该事件已经完成处理过程,不需要其他处理函数参与处理过程,这样事件就不会再继续进行传递
如果监听器处理函数的返回值为false,则表示该事件没有完成处理过程,或需要其他处理函数捕获到该事件,事件会被传递给其他的事件处理函数
上传一个menu按键事件处理
1 package cn.edu.zwu.tel;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.ContextMenu;
6 import android.view.Menu;
7 import android.view.MenuItem;
8 import android.view.MenuItem.OnMenuItemClickListener;
9 import android.view.View;
10 import android.view.ContextMenu.ContextMenuInfo;
11 import android.widget.TextView;
12
13 public class LayoutMenuEvent01Activity extends Activity{
14 /** Called when the activity is first created. */
15 TextView LabelView = null;
16 final static int it1=Menu.FIRST;
17 final static int it2=Menu.FIRST+1;
18 final static int it3=Menu.FIRST+2;
19 MenuItem mit1,mit2,mit3;
20 @Override
21 public void onCreate(Bundle savedInstanceState)
22 {
23 super.onCreate(savedInstanceState);
24 setContentView(R.layout.main);
25 LabelView = (TextView)findViewById(R.id.label);
26 registerForContextMenu(LabelView);
27 }
28
29 @Override
30 public void onCreateContextMenu(ContextMenu menu,
31 View v, ContextMenuInfo menuInfo)
32 {
33 menu.setHeaderTitle("菜单响应示例");
34 menu.add(0,it1,0,"菜单子项1");
35 menu.add(0,it2,0,"菜单子项2");
36 menu.add(0,it3,0,"菜单子项3");
37 mit1=menu.findItem(it1);
38 mit2=menu.findItem(it2);
39 mit3=menu.findItem(it3);
40
41
42 mit1.setOnMenuItemClickListener(new OnMenuItemClickListener(){
43 @Override
44 public boolean onMenuItemClick (MenuItem item)
45 {
46 LabelView.setText("菜单子项1");
47 return true;
48 }
49 });
50 mit2.setOnMenuItemClickListener(new OnMenuItemClickListener(){
51 @Override
52 public boolean onMenuItemClick (MenuItem item)
53 {
54 LabelView.setText("菜单子项2");
55 return true;
56 }
57 });
58 mit3.setOnMenuItemClickListener(new OnMenuItemClickListener(){
59 @Override
60 public boolean onMenuItemClick (MenuItem item)
61 {
62 LabelView.setText("菜单子项3");
63 return true;
64 }
65 });
66 }
效果演示:
演示第二个屏幕事件处理,先演示是基于监听接口的事件处理
第一步:编写main.xml布局文件
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent">
6 <TextView android:id="@+id/touch_area"
7 android:layout_width="fill_parent"
8 android:layout_height="300dip"
9 android:background="#80A0FF"
10 android:textColor="#FFFFFF"
11 android:text="触摸事件测试区域">
12 </TextView>
13 <TextView android:id="@+id/history_label"
14 android:layout_width="wrap_content"
15 android:layout_height="wrap_content"
16 android:text="历史数据量:" >
17 </TextView>
18 <TextView android:id="@+id/event_label"
19 android:layout_width="wrap_content"
20 android:layout_height="wrap_content"
21 android:text="触摸事件:" >
22 </TextView>
23 </LinearLayout>
第二步:编写LayoutTouch01Activity.java这个文件
1 package cn.edu.zwu.tel;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.MotionEvent;
6 import android.view.View;
7 import android.widget.TextView;
8
9 public class LayoutTouch01Activity extends Activity
10 {
11 TextView labelView = null;
12 TextView historyView=null;
13 @Override
14 public void onCreate(Bundle savedInstanceState)
15 {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.main);
18
19 TextView touchView = (TextView)findViewById(R.id.touch_area);
20 labelView = (TextView)findViewById(R.id.event_label);
21 historyView = (TextView)findViewById(R.id.history_label);
22
23 touchView.setOnTouchListener(new View.OnTouchListener()
24 {
25 @Override
26 public boolean onTouch(View v, MotionEvent event)
27 {
28 int action = event.getAction();
29 switch (action)
30 {
31 case (MotionEvent.ACTION_DOWN):
32 Display("ACTION_DOWN",event);
33 break;
34 case (MotionEvent.ACTION_UP):
35 int historySize = ProcessHistory(event);
36 historyView.setText("历史数据量:"+historySize);
37 Display("ACTION_UP",event);
38 break;
39 case (MotionEvent.ACTION_MOVE):
40 Display("ACTION_MOVE",event);
41 break;
42 }
43
44 return true;
45 }
46 });
47
48 }
49
50
51 private void Display(String eventType, MotionEvent event)
52 {
53 int x = (int)event.getX();
54 int y = (int)event.getY();
55 float pressure = event.getPressure();
56 float size = event.getSize();
57 int RawX = (int)event.getRawX();
58 int RawY = (int)event.getRawY();
59
60 String msg = "";
61 msg += "事件类型:" + eventType + "\n";
62 msg += "相对坐标:"+String.valueOf(x)+","+String.valueOf(y)+"\n";
63 msg += "绝对坐标:"+String.valueOf(RawX)+","+String.valueOf(RawY)+"\n";
64 msg += "触点压力:"+String.valueOf(pressure)+", ";
65 msg += "触点尺寸:"+String.valueOf(size)+"\n";
66 labelView.setText(msg);
67 }
68
69 private int ProcessHistory(MotionEvent event)
70 {
71 int historySize = event.getHistorySize();
72 for (int i = 0; i < historySize; i++) {
73 long time = event.getHistoricalEventTime(i);
74 float pressure = event.getHistoricalPressure(i);
75 float x = event.getHistoricalX(i);
76 float y = event.getHistoricalY(i);
77 }
78 return historySize;
79 }
80 }
效果图:
再编写一个基于回调函数的,这里要注意到是基于接口是对固定的屏幕进行监听,而回调函数是对整个屏幕进行了监听,main.xml文件是没变化的。
贴个主程序代码:
1 package cn.edu.zwu.tel;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.MotionEvent;
6 import android.view.View;
7 import android.widget.TextView;
8
9 public class LayoutTouch01Activity extends Activity
10 {
11 TextView labelView = null;
12 TextView historyView=null;
13 @Override
14 public void onCreate(Bundle savedInstanceState)
15 {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.main);
18
19 TextView touchView = (TextView)findViewById(R.id.touch_area);
20 labelView = (TextView)findViewById(R.id.event_label);
21 historyView = (TextView)findViewById(R.id.history_label);
22
23 }
24
25 public boolean onTouchEvent( MotionEvent event)
26 {
27 int action = event.getAction();
28 switch (action)
29 {
30 case (MotionEvent.ACTION_DOWN):
31 Display("ACTION_DOWN",event);
32 break;
33 case (MotionEvent.ACTION_UP):
34 int historySize = ProcessHistory(event);
35 historyView.setText("历史数据量:"+historySize);
36 Display("ACTION_UP",event);
37 break;
38 case (MotionEvent.ACTION_MOVE):
39 Display("ACTION_MOVE",event);
40 break;
41 }
42
43 return true;
44 }
45
46 private void Display(String eventType, MotionEvent event)
47 {
48 int x = (int)event.getX();
49 int y = (int)event.getY();
50 float pressure = event.getPressure();
51 float size = event.getSize();
52 int RawX = (int)event.getRawX();
53 int RawY = (int)event.getRawY();
54
55 String msg = "";
56 msg += "事件类型:" + eventType + "\n";
57 msg += "相对坐标:"+String.valueOf(x)+","+String.valueOf(y)+"\n";
58 msg += "绝对坐标:"+String.valueOf(RawX)+","+String.valueOf(RawY)+"\n";
59 msg += "触点压力:"+String.valueOf(pressure)+", ";
60 msg += "触点尺寸:"+String.valueOf(size)+"\n";
61 labelView.setText(msg);
62 }
63
64 private int ProcessHistory(MotionEvent event)
65 {
66 int historySize = event.getHistorySize();
67 for (int i = 0; i < historySize; i++) {
68 long time = event.getHistoricalEventTime(i);
69 float pressure = event.getHistoricalPressure(i);
70 float x = event.getHistoricalX(i);
71 float y = event.getHistoricalY(i);
72 }
73 return historySize;
74 }
75 }
效果图:
这里是在模拟器上仿真的,所以不能显示压力大小