如何区分长按键和普通按键?

发布于 2024-12-17 18:55:25 字数 761 浏览 3 评论 0原文

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

到目前为止,我已经在 Activity 中重写了这两个方法:

@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 中全部完成并使用重复次数/毫秒来检测它?

I'm trying to override the functionality of the back key press. When the user presses it once, I want it to come back to the previous screen. However, when the back key is long-pressed (for, let's say, two seconds or more), I want to exit the application.

By now, I have overriden these two methods in my activity:

@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);
}

But the onKeyLongPress callback is never called, because the event is always received by the onKeyDown method.

Is there any way of having both methods working? Or has it to be done all in the onKeyDown and use the number of repetitions/milliseconds to detect it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不如归去 2024-12-24 18:55:25

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

您需要做的是:

  1. 在返回 true 之前,按照 文档
  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 );
  }

The reason why onKeyLongPress is never called, is that you return true in onKeyDown without telling the framework that this might be a long press - causing the KeyEvent to stop its flow through the different event handlers.

What you need to do is this:

  1. Before you return true, call event.startTracking() as explained in the documentation.
  2. Handle the long press in onKeyLongPress.

Implement as below and it will work:

  @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 );
  }
潜移默化 2024-12-24 18:55:25

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

Why not use onKeyUp() as well as onKeyDown()? During onKeyDown() you do not know whether it is a long press or not, because that is called as soon as the key is pressed and you do not know how long the user intends to hold the key down for. As KasperMoerch correctly says, you need to call startTracking in your onKeyDown() method, and return true. Then in your onKeyUp() you can call event.isTracking() and event.isLongPress() to determine whether to handle things as a long press or short press.

公布 2024-12-24 18:55:25

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

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

代码:

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);
}

I think the best way to handle it is as such.

The only downside I can see here, is that single clicking the menu button doesn't make a sound in case the user has it enabled. Maybe there is a way to check this setting and use it, or call the default behavior.

Code:

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);
}
清眉祭 2024-12-24 18:55:25

在我看来,当你重写 onkeypress 和 onkeylongpress 时。每次按一次或长时间按键时,它会自动调用onkeypress。为了避免这种情况,你必须在 onkeypress 中编写 event.starttracking() ,但这只会导致长按键功能,在这种情况下按键不起作用。

对于这个解决方案。您应该覆盖 onkeydown 和 onkeyup。创建一个 bool 并使用它。这是我的代码:

var isKeyDown: Boolean = false

override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
    return when (keyCode) {
        KeyEvent.KEYCODE_VOLUME_DOWN -> {
            isKeyDown = false
            true
        }
        KeyEvent.KEYCODE_VOLUME_UP -> {
            isKeyDown = false
            true
        }

        else -> super.onKeyUp(keyCode, event)
    }
}

/** When key down event is triggered, relay it via local broadcast so fragments can handle it */
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
    return when (keyCode) {
        KeyEvent.KEYCODE_VOLUME_DOWN -> {
            if (!isKeyDown) {
                val intent =
                    Intent(KEY_EVENT_ACTION).apply { putExtra(KEY_EVENT_EXTRA, keyCode) }
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
            }
            isKeyDown = true
            true
        }
        KeyEvent.KEYCODE_VOLUME_UP -> {
            if (!isKeyDown) {
                val intent =
                    Intent(KEY_EVENT_ACTION).apply { putExtra(KEY_EVENT_EXTRA, keyCode) }
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
            }
            isKeyDown = true
            true
        }

        else -> super.onKeyDown(keyCode, event)
    }
}

In my opinion when you override onkeypress and onkeylongpress. It will automatically call onkeypress everytime you press the key for once or for long. To avoid this you have to write event.starttracking() in onkeypress, but it will result only in functionality of long key press, key press would not work in this scenerio.

For this soloution. You should override onkeydown and onkeyup. make a bool and work with it. Heres my code:

var isKeyDown: Boolean = false

override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
    return when (keyCode) {
        KeyEvent.KEYCODE_VOLUME_DOWN -> {
            isKeyDown = false
            true
        }
        KeyEvent.KEYCODE_VOLUME_UP -> {
            isKeyDown = false
            true
        }

        else -> super.onKeyUp(keyCode, event)
    }
}

/** When key down event is triggered, relay it via local broadcast so fragments can handle it */
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
    return when (keyCode) {
        KeyEvent.KEYCODE_VOLUME_DOWN -> {
            if (!isKeyDown) {
                val intent =
                    Intent(KEY_EVENT_ACTION).apply { putExtra(KEY_EVENT_EXTRA, keyCode) }
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
            }
            isKeyDown = true
            true
        }
        KeyEvent.KEYCODE_VOLUME_UP -> {
            if (!isKeyDown) {
                val intent =
                    Intent(KEY_EVENT_ACTION).apply { putExtra(KEY_EVENT_EXTRA, keyCode) }
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
            }
            isKeyDown = true
            true
        }

        else -> super.onKeyDown(keyCode, event)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文