一、事件处理:
为用户动作提供响应的机制就是事件处理。两种事件处理方式:
1. 基于回调的事件处理
主要做法:
重写Android组件特定的回调方法,或者重写Activity的回调方法。 Android为绝大部分界面组件都提供了事件响应的回调方法,开发者只要重写它们即可。 基于回调的事件处理可用于处理一些具有通用性的事件,基于回调的事件处理代码会显得比较简洁。但对于某些特定的事件,无法使用基于回调的事件处理,只能采用基于监听的事件处理。2. 基于监听器的事件处理
主要做法:
为Android界面组件绑定特定的事件监听器。事件监听的处理模型:
主要涉及三类对象: a. Event Source(事件源):事件发生的场所,通常就是各个组件,例如按钮、窗口、菜单等。 b. Event(事件):事件封装了界面组件上发生的特定事情(通常就是一次用户操作)。 如果程序需要获得界面组件上所发生事件的相关信息,一般通过Event对象来取得。 c. EventListener(事件监听器):负责监听事件源所发生的事件,并对各种事件做出相应的相应。事件处理器(Event Handler):
事件响应的动作实际上市一系列程序语句,通常以方法的形式组织起来。但Java是面向对象的编程语言,方法不能独立存在,所以必须以类的形式来组织这些方法,所以事件监听器的核心就是它所包含的方法,这些方法也被称为事件处理器。思路:
1.在main.xml中设置布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="center_horizontal"
>
<EditText
android:id="@+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:editable="false"
android:cursorVisible="false"
android:textSize="12pt"
/>
<!-- 定义一个按钮,该按钮将作为事件源 -->
<Button
android:id="@+id/bn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="单击我"
/>
</LinearLayout>
2.编程为该按钮绑定一个事件监听器
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//获取应用程序中的bn按钮
Button bn = (Button)findViewById(R.id.bn);
//为按钮绑定事件监听器
bn.setOnClickListener(new MyClickListener());
}
//定义一个单击事件的监听器
class MyClickListener implements OnClickListener{
//实现监听器必须实现的方法,该方法将会作为事件处理器
public void onClick(View arg0){
EditText txt = (EditText)findViewById(R.id.txt);
txt.setText("bn按钮被单击了");
}
}
}
步骤:
a. 获取普通界面组件(事件源),也就是被监听的对象。
b. 实现事件监听器类,该监听器类是一个特殊的Java类,必须实现一个XxxListener接口。
c. 调用事件源的setXxxListener方法将事件监听器对象注册给普通组件(事件源)。
注:实现事件监听器是整个事件处理的核心
实例:控制飞机移动
下面以一个简单的飞机游戏为例来介绍键盘事件的监听:游戏中的飞机回随用户单击键的动作而移动:单击不同的键,飞机向不同方法移动。思路:
为了实现该程序,我们先开发一个自定义View,该View负责绘制游戏的飞机,该View的代码如下。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
public class PlaneView extends View {
public float currentX;
public float currentY;
Bitmap plane;
public PlaneView(Context context){
super(context);
//定义飞机图片
plane = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
setFocusable(true);
}
public void onDraw(Canvas canvas){
super.onDraw(canvas);
//创建画笔
Paint p = new Paint();
//绘制飞机
canvas.drawBitmap(plane,currentX,currentY,p);
}
}
import android.app.Activity;
import android.os.Bundle;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;
import android.view.Window;
import android.view.WindowManager;
public class PlaneGame extends Activity {
//定义飞机的移动速度
private int speed = 12;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//去掉窗口标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
//全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN );
//创建PlaneView组件
final PlaneView planeView = new PlaneView(this);
setContentView(planeView);
planeView.setBackgroundResource(R.drawable.ic_launcher);
//获取窗口管理器
WindowManager windowManger = getWindowManager();
Display display = windowManger.getDefaultDisplay();
//获得屏幕宽和高
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
//设置飞机的初始位置
planeView.currentX = screenWidth/2;
planeView.currentY = screenHeight -40;
//为draw组件键盘事件绑定监听器
planeView.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View source, int keyCode, KeyEvent event){
//获取由哪个键触发的事件
switch(event.getKeyCode()){
//控制飞机下移
case KeyEvent.KEYCODE_DPAD_DOWN:
planeView.currentY+=speed;
break;
//控制飞机上移
case KeyEvent.KEYCODE_DPAD_UP:
planeView.currentY-=speed;
break;
//控制飞机左移
case KeyEvent.KEYCODE_DPAD_LEFT:
planeView.currentX-=speed;
break;
//控制飞机右移
case KeyEvent.KEYCODE_DPAD_RIGHT:
planeView.currentX+=speed;
break;
}
//通知planeView组件重绘
planeView.invalidate();
return true;
}
});
}
}
基于事件监听的处理模型中,事件监听器必须实现事件监听器接口,Android为不同的界面组件提供了不同的监听器接口,这些接口通常以内部类的形式存在。
以View类为例,它包含了如下几个内部接口。
View.OnClickListener:单击事件的事件监听器必须实现的接口。
View.OnCreateContexMenuListener:创建上下文菜单事件的事件监听器必须实现的接口。
View.OnFocusChangeListener:焦点改变事件的事件监听器必须事件的接口。
View.OnKeyListener:按键事件的事件监听器必须实现的接口。
View.OnLongClickListener:长单击事件的事件监听器必须实现的接口。
View.OnTouchLister:触摸屏事件的事件监听器必须实现的接口。
事件监听器,其实就是实现了特定接口的Java类的实例。在程序中实现事件监听器,通常有如下几种形式:
内部类形式:将事件监听器类定义成当前类的内部类。
外部类形式:将事件监听器类定义成一个外部类。
Activity本身作为事件监听器类:让Activity本身实现监听器接口,并实现事件处理方法。
匿名内部类形式:使用匿名内部类创建事件监听器对象。