Android 响应用户事件的方法
同绘图一样, View 也是通过回调函数来响应用户事件的。键盘事件的回调函数有多个,以对应不同的事件,我们暂时只用到 onKeyDown ,对应按键被按下的事件,其他函数以后用到再介绍。让我们重载 onKeyDown (重载一个函数的方法前面章节有介绍)
@Override
public boolean onKeyDown( int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
return super .onKeyDown(keyCode, event);
}
onKeyDown 有两个参数: keyCode 和 event ,通过 keyCode 能判断是哪个键被按下, event 比较复杂,包含了这次按键更多的信息,我们暂时先不考虑它。
现在我们要通过按键控制主角向四个方向移动。所谓移动,就是将主角的图像在不同的位置显示出来,也就是改变函数 drawBitmap 中的第二、第三个参数。比如用户按下右方向键,我们就把横坐标增加,这样下次显示出来的时候,主角就会往右一点。为了节约时间,我们就把刚刚显示的图片 BattleCity 作为主角好了。首先定义两个全局变量 x 和 y ,然后在 onKeyDown 中改变 x 、 y 的值,然后重绘 View 。因为代码没有什么难度,所以不做讲解了。
public class GameView extends View {
int x =0, y =0;
……
@Override
protected void onDraw(Canvas canvas) {
……
canvas.drawBitmap( bmp , x , y , new Paint());
}
@Override
public boolean onKeyDown( int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
switch (keyCode) {
case KeyEvent. KEYCODE_DPAD_UP :
y -= 10;
break ;
case KeyEvent. KEYCODE_DPAD_DOWN :
y += 10;
break ;
case KeyEvent. KEYCODE_DPAD_LEFT :
x -= 10;
break ;
case KeyEvent. KEYCODE_DPAD_RIGHT :
x += 10;
break ;
}
postInvalidate(); // 通知系统重绘 View
======黑软基地手机资讯频道======
return super .onKeyDown(keyCode, event);
}
}
完成后我们肯定很想测试一下,但是此时你会发现,按键根本没有任何反应。这就是我们要特殊指出的地方。 View 被显示时,缺省情况下没有获得焦点,就是说,按键动作没有发送给 View ,所以需要在构造函数中增加一句
public GameView(Context context) {
……
setFocusable( true );
}
再运行程序,看看图片是否按照我们的指令运动起来了。
前面说过,很多手机没有硬键盘,所以我们需要一个软键盘的解决方案。软键盘就是在屏幕上显示一个键盘,然后响应用户的触摸屏操作,模拟成键盘操作。对于坦克大战,我们只需要在屏幕上显示一个模拟的游戏手柄(显示图片的方法大家没有忘记吧,显示位置可以根据模拟器自行调整):
在用户触摸模拟手柄上的方向键和开火键时进行相应的操作。我们拿方向键做演示,步骤如下:首先确定四个方向键在屏幕上的区域(上图的红色方框),然后在触摸屏事件的响应函数中判断事件是否发生在方向键区域中,最后如果事件发生在区域中进行相应的操作。
下面,我们引入一个非常有用的类 Rect ( RectF 与 Rect 基本相同,不过以 float 作为坐标参数), rect 是 rectangle 的简写,顾名思义,这个类代表了一个矩形。 Rect 通过矩形 4 个边来定义这个矩形的范围。他们分别是 left , right , top , bottom ,如图所示:
转化为屏幕坐标, top 是矩形坐上角的纵坐标, left 是矩形坐上角的横坐标, right 是矩形右下角的横坐标, buttom 是右下角的纵坐标。有了 Rect 我们就可以方便的表示虚拟手柄各个键的位置。同时 Rect 还提供了一些很有用的函数,其中 Rect.contains(x, y) 能够判断点 (x, y) 是否在矩形框中,正好是我们需要的。
现在我们就可以开始编码了,首先为虚拟键盘的方向键创建 Rect (可以用绘图工具测量坐标):
Rect rKeyUp = new Rect(56,290,86,320);
Rect rKeyDown = new Rect(56, 350, 86, 380);
Rect rKeyLeft = new Rect(26, 320, 56, 350);
======黑软基地手机资讯频道======
Rect rKeyRight = new Rect(86, 320, 116, 350);
然后重载触摸屏响应函数:
@Override
public boolean onTouchEvent(MotionEvent arg0) {
// TODO Auto-generated method stub
return super .onTouchEvent(arg0);
}
下面我们要做的是,首先判断触摸屏操作是不是按下,如果是,取得坐标( x , y ),然后判断坐标所在的按键,做出相应的操作
@Override
public boolean onTouchEvent(MotionEvent arg0) {Auto-generated method stub
if (arg0.getAction() == MotionEvent. ACTION_DOWN ) {
int ax = ( int ) arg0.getX();
int ay = ( int ) arg0.getY();
if ( rKeyUp .contains(ax, ay)) {
y -= 10;
} else if ( rKeyDown .contains(ax, ay)) {
y += 10;
} else if ( rKeyLeft .contains(ax, ay)) {
x -= 10;
} else if ( rKeyRight .contains(ax, ay)) {
x += 10;
}
postInvalidate(); // 不要忘记刷新屏幕
}
return super .onTouchEvent(arg0);
}
现在让我们运行一下,每次用鼠标点击模拟手柄的方向键,图片就会移动