如何区分长按和普通按键?(涉及IT技术)

10

我试图覆盖后退按键的功能。当用户按下它一次时,我希望它返回到上一个屏幕。然而,当长按后退键(例如,长按两秒或更长时间)时,我希望退出应用程序。

到目前为止,我在我的活动中重写了这两个方法:

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


嘿,看一下这个链接 keyevent doc - Vishal Pawar
4个回答

18
< p > 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 方法中检测长按,对吧? - Mister Smith
我编辑了代码中的注释以显示我的意图。只有在按键短时我才想在 onKeyDown 中返回 true。否则传递给长按键处理程序。 - Mister Smith

2
为什么不同时使用'onKeyUp()'和'onKeyDown()'?在'onKeyDown()'期间,您无法知道它是长按还是短按,因为该方法在按键按下时立即调用,并且您不知道用户打算按下多长时间。如KasperMoerch所说,您需要在'onKeyDown()'方法中调用'startTracking'并返回'true'。然后,在'onKeyUp()'中,可以调用'event.isTracking()'和'event.isLongPress()'来确定是要将其视为长按还是短按。

不起作用。尽管我按住按钮将近5秒钟,但“isTracking”返回true,而“isLongPress”返回false。也许这在模拟器上无法测试? - Mister Smith

2

我认为处理它的最佳方式如下。

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

代码:

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

0
在我看来,当你重写 onkeypress 和 onkeylongpress 时,它会自动调用 onkeypress 每次你按下键盘一次或长按。为了避免这种情况,你必须在 onkeypress 中编写 event.starttracking(),但这只会导致长按功能可用,按键在这种情况下不起作用。
为了解决这个问题,你应该重写 onkeydown 和 onkeyup,并使用一个布尔值进行操作。以下是我的代码:
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)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接