William Hua的Blog

2009-04-08

Android MapView的setOnKeyListerner有什么问题?[Updated]

Filed under: Android,嵌入式开发 — 标签:, , — William Hua @ 23:14


今天想要实现一个基于MapView的小游戏,用户可以在地图上用上、下、左、右四个键来操作一个在地图上的一个小汽车。所以第一步就是要在MapView中添加一个按键响应的Listener来处理这四个键。

我一开始使用的是MapView的setOnKeyListener方法来设置一个OnKeyListener,并且通过一个内部类来实现它。看下面的代码,逻辑很简单,拿到MapView的实例mapView以后马上设置OnKeyListener,Linstener中就实现一个onKey方法来捕捉按键。

mapView = (MapView) findViewById(R.id.mapview);
// set on key listener
mapView.setOnKeyListener(onKeyListener);

// Inner class for OnKeyListener
final private OnKeyListener onKeyListener = new OnKeyListener() {

       @Override
       public boolean onKey(View v, int keyCode, KeyEvent event) {
               boolean ret = false;

               Log.i("SuperMap", "event.getAction()=" + event.getAction());
               Log.i("SuperMap", "keyCode=" + keyCode);
               if (event.getAction() == KeyEvent.ACTION_DOWN) // key pressed down

                       switch (keyCode) {

                       case KeyEvent.KEYCODE_DPAD_UP:
                               Toast.makeText(SuperMap.this, "UP", Toast.LENGTH_SHORT)
                                               .show();
                               ret = true;
                               break;
                       case KeyEvent.KEYCODE_DPAD_DOWN:
                               Toast.makeText(SuperMap.this, "DOWN", Toast.LENGTH_SHORT)
                                               .show();
                               ret = true;
                               break;
                       case KeyEvent.KEYCODE_DPAD_LEFT:
                               Toast.makeText(SuperMap.this, "LEFT", Toast.LENGTH_SHORT)
                                               .show();
                               ret = true;
                               break;
                       case KeyEvent.KEYCODE_DPAD_RIGHT:
                               Toast.makeText(SuperMap.this, "RIGHT", Toast.LENGTH_SHORT)
                                               .show();
                               ret = true;
                               break;
                       default:
                               // do nothing here
                               ret = false;
                               break;
                       }
               else {
                       // do nothing when key released or multiple keys pressed at the
                       // same time
                       ret = false;
               }
               return ret;
       }
};

编译没有问题,但是程序跑起来以后,完全不响应按键,而且LogCat中没有任何输出,就好像这个Listener根本没有注册成功一样。

这个时候我想起了另一个方法,即MapView类的onKeyDown() 方法。这个方法的实现更加简单,拿到实例mapView以后设置Listener的步骤也不需要了,我们只要直接在当前类里面Override父类MapView的onKeyDown() 方法即可,逻辑和第一种方法一样。

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
       boolean ret = false;

       Log.i("SuperMap", "event.getAction()=" + event.getAction());
       Log.i("SuperMap", "keyCode=" + keyCode);
       if (event.getAction() == KeyEvent.ACTION_DOWN) // key pressed down

               switch (keyCode) {
                   //同第一种方法,这里略去
               }
       else {
               // do nothing when key released or multiple keys pressed at the
               // same time
               ret = false;
       }
       return ret;
}

让我不解的是,这种方法居然就可以相应上、下、左、右这4个按键。按照我的理解,只要当前的焦点在MapView,这两种方法应该没有什么区别才是。
没辙,只好上讨论组去问问了,有任何新的消息我会在这里贴出来。

Update: 查了讨论组,要解决setOnKeyListener不工作的问题,添加一句代码即可,问题是SDK的文档里似乎没有提到。
我们只要在

// set on key listener
mapView.setOnKeyListener(onKeyListener);

后面追加一句代码即可

mapView.setFocusable(true);

2 条评论 »

  1. [...] 这次遇到的这个问题和上次MapView中setOnKeyListener遇到的问题挺类似,其实都是对SDK的了解不够全面,遇到了一次记住了就好。不过话说回来,Google在文档方面确实需要加强了,起码可以在OnGestureListener中说明需要满足那些条件才可以保证手势被正确识别。 [...]

    Pingback by 简述Android触摸屏手势识别 - Touch 3G — 2009-04-26 @ 22:10

  2. hi,我在onKeyDown里把事件dispatch出去了也是可以的,因为我跟踪发现onKeyDown里面会去执行这个dispatch的动作,似乎有设置dispatchKeyEvent的话才把事件送给onKeyListener处理。

    评论 by egg — 2009-09-02 @ 10:19

这篇文章上的评论的 RSS feed TrackBack URL

留下评论

Powered by WordPress