【问题标题】:How to differentiate between long key press and regular key press?如何区分长按键和普通按键?
【发布时间】:2012-01-03 20:02:20
【问题描述】:

我正在尝试覆盖后退键的功能。当用户按下它一次时,我希望它回到上一个屏幕。但是,当长按返回键时(比如说,两秒或更长时间),我想退出应用程序。

到目前为止,我已经在我的活动中覆盖了这两个方法:

@Override
public boolean onKeyDown( int keyCode, KeyEvent event){
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        //manage short keypress
        return true;
    }
    return super.onKeyDown(keyCode, event);
}

@Override
public boolean onKeyLongPress( int keyCode, KeyEvent event){
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        //manage long keypress (different code than short one)
        return true;
    }
    return super.onKeyLongPress(keyCode, event);
}

但永远不会调用onKeyLongPress 回调,因为事件总是由onKeyDown 方法接收。

有没有办法让这两种方法都起作用?还是必须全部在onKeyDown中完成,并使用重复/毫秒数来检测?

【问题讨论】:

标签: android onkeypress long-press


【解决方案1】:

我认为最好的处理方式就是这样。

我在这里看到的唯一缺点是,如果用户启用它,单击菜单按钮不会发出声音。也许有办法检查这个设置并使用它,或者调用默认行为。

代码:

private boolean _handledMenuButton=false;

@Override
public boolean onKeyUp(final int keyCode,final KeyEvent event) {
    switch(keyCode) {
        case KeyEvent.KEYCODE_MENU:
          if (!_handledMenuButton) {
              //Handle single clicking here
          }
          _handledMenuButton=false;
          return true;
    }
    return super.onKeyUp(keyCode,event);
}

@Override
public boolean onKeyLongPress(final int keyCode, final KeyEvent event) {
    switch(keyCode) {
        case KeyEvent.KEYCODE_MENU:
          //Handle long clicking here
          _handledMenuButton=true;
          return true;
    }
    return super.onKeyLongPress(keyCode,event);
}

@Override
public boolean onKeyDown(final int keyCode,final KeyEvent event) {
    switch(keyCode) {
        case KeyEvent.KEYCODE_MENU:
            _handledMenuButton=false;
            event.startTracking();
            return true;
    }
    return super.onKeyDown(keyCode,event);
}

【讨论】:

    【解决方案2】:

    onKeyLongPress 从未被调用的原因是,您在 onKeyDown 中返回 true 却没有告诉框架这可能是长按 - 导致 KeyEvent 停止通过不同的事件处理程序。

    你需要做的是:

    1. 在返回 true 之前,请按照 documentation 中的说明调用 event.startTracking()
    2. onKeyLongPress 中处理长按。

    如下实现,它将起作用:

      @Override
      public boolean onKeyDown( int keyCode, KeyEvent event ) {
        if( keyCode == KeyEvent.KEYCODE_BACK ) {
          event.startTracking();
          return true; 
        }
        return super.onKeyDown( keyCode, event );
      }
    
      @Override
      public boolean onKeyUp( int keyCode, KeyEvent event ) {
        if( keyCode == KeyEvent.KEYCODE_BACK ) {
          //Handle what you want on short press.      
          return true; 
        }
    
        return super.onKeyUp( keyCode, event );
      }
    
      @Override
      public boolean onKeyLongPress( int keyCode, KeyEvent event ) {
        if( keyCode == KeyEvent.KEYCODE_BACK ) {
          //Handle what you want in long press.
          return true;
        }
        return super.onKeyLongPress( keyCode, event );
      }
    

    【讨论】:

    • 问题是,在返回true之前,我必须做一些完全不同的事情,如果事件是针对常规按下或长按。所以无论如何,我必须在调用startTracking之前检测到onKeyDown方法上的长按,不是吗?
    • 我在我的代码中编辑了 cmets 以显示我的意思。如果按键很短,我只想在onKeyDown 中返回true。否则传播到长按键处理程序。
    【解决方案3】:

    为什么不使用onKeyUp()onKeyDown()?在onKeyDown() 期间,您不知道它是否是长按,因为只要按下键就会调用它并且您不知道用户打算按住键多长时间。正如 KasperMoerch 正确所说,您需要在 onKeyDown() 方法中调用 startTracking,然后返回 true。然后在你的onKeyUp()中你可以调用event.isTracking()event.isLongPress()来决定是长按还是短按来处理。

    【讨论】:

    • 不起作用。 isTracking 返回 true 但 isLongPress 返回 false,尽管我按住按钮将近 5 秒。也许这不能在模拟器上测试?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    • 2021-12-15
    • 2020-04-23
    • 2016-05-21
    相关资源
    最近更新 更多