onKeyDown和onKeyLongPress

我希望我的应用程序对音量按钮的正常和长按键事件的反应不同。

我已经看过了 ,但如果按下音量按钮,我会在获得KeyLongPressed事件之前获得很多KeyDown事件。

我希望有一个或另一个,而不是两个,所以我可以在短时间内调整音量并长按跳过音轨。

你能帮帮我吗?

这是我的代码:

  @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { Log.d("Test", "Long press!"); return true; } return super.onKeyLongPress(keyCode, event); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { event.startTracking(); Log.d("Test", "Short"); return true; } return super.onKeyDown(keyCode, event); } 

任何帮助赞赏! – 虹膜

这是我写的代码。 它就像一个魅力。 也许你可以优化它以获得更好的逻辑。 但是你会明白这一点。 关键是使用标志。 短按是按下音量按钮短时间并释放的按键 。 所以onKeyUp是帮助我们检测短按的那个。

 package com.example.demo; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; public class TestVolumeActivity extends Activity { boolean flag = false; boolean flag2 = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash_screen); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_splash_screen, menu); return true; } @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { Log.d("Test", "Long press!"); flag = false; flag2 = true; return true; } return super.onKeyLongPress(keyCode, event); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { event.startTracking(); if (flag2 == true) { flag = false; } else { flag = true; flag2 = false; } return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { event.startTracking(); if (flag) { Log.d("Test", "Short"); } flag = true; flag2 = false; return true; } return super.onKeyUp(keyCode, event); } } 

所有长按的Logcat(未检测到短按):

 10-18 02:06:15.369: D/Test(16834): Long press! 10-18 02:06:18.683: D/Test(16834): Long press! 10-18 02:06:21.566: D/Test(16834): Long press! 10-18 02:06:23.738: D/Test(16834): Long press! 

适用于所有短按的Logcat:

 10-18 02:07:42.422: D/Test(16834): Short 10-18 02:07:43.203: D/Test(16834): Short 10-18 02:07:43.663: D/Test(16834): Short 10-18 02:07:44.144: D/Test(16834): Short 

当我即将发布我的答案时,我发现有人已经得到某种解决方案……

但这是我的,简单,就像一个魅力。 只有一面旗帜;)

此代码检测到短按和长按,当长按发生时,不会发出短按!

注意:如果你想要正常的音量上升和下降行为,请将onKeyPress方法中的return true更改为超级调用,如下所示:

 event.startTracking(); if(event.getRepeatCount() == 0){ shortPress = true; } //return true; return super.onKeyDown(keyCode, event); 

没有超级电话的代码:

 private boolean shortPress = false; @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { shortPress = false; Toast.makeText(this, "longPress", Toast.LENGTH_LONG).show(); return true; } //Just return false because the super call does always the same (returning false) return false; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { if(event.getAction() == KeyEvent.ACTION_DOWN){ event.startTracking(); if(event.getRepeatCount() == 0){ shortPress = true; } return true; } } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { if(shortPress){ Toast.makeText(this, "shortPress", Toast.LENGTH_LONG).show(); } else { //Don't handle longpress here, because the user will have to get his finger back up first } shortPress = false; return true; } return super.onKeyUp(keyCode, event); } 

这里的代码是添加了音量增加键,只需选择你的一面;)

 private boolean shortPress = false; @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { shortPress = false; Toast.makeText(this, "longPress Volume Down", Toast.LENGTH_LONG).show(); return true; } else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){ shortPress = false; Toast.makeText(this, "longPress Volume Up", Toast.LENGTH_LONG).show(); return true; } //Just return false because the super call does always the same (returning false) return false; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { if(event.getAction() == KeyEvent.ACTION_DOWN){ event.startTracking(); if(event.getRepeatCount() == 0){ shortPress = true; } return true; } } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { if(shortPress){ Toast.makeText(this, "shortPress Volume Down", Toast.LENGTH_LONG).show(); } else { //Don't handle longpress here, because the user will have to get his finger back up first } shortPress = false; return true; } else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){ if(shortPress){ Toast.makeText(this, "shortPress Volume up", Toast.LENGTH_LONG).show(); } else { //Don't handle longpress here, because the user will have to get his finger back up first } shortPress = false; return true; } return super.onKeyUp(keyCode, event); } 

根据SDK的正确方式处理长按按钮。

 import android.app.Activity; import android.util.Log; import android.view.KeyEvent; public class TestVolumeActivity extends Activity { private static final String TAG = TestVolumeActivity.class.getSimpleName(); @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if( keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { event.startTracking(); return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){ Log.d(TAG, "Long press KEYCODE_VOLUME_UP"); return true; } else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){ Log.d(TAG, "Long press KEYCODE_VOLUME_DOWN"); return true; } return super.onKeyLongPress(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if((event.getFlags() & KeyEvent.FLAG_CANCELED_LONG_PRESS) == 0){ if(keyCode == KeyEvent.KEYCODE_VOLUME_UP){ Log.e(TAG, "Short press KEYCODE_VOLUME_UP"); return true; } else if(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){ Log.e(TAG, "Short press KEYCODE_VOLUME_DOWN"); return true; } } return super.onKeyUp(keyCode, event); } } 

我不知道这个答案是否会为您的问题提供可接受的解决方案,因为它依赖于持续不断地获取频繁的 KeyDown事件。

您可以尝试在抛出最后一个KeyDown事件时记住系统时间(我将其命名为tLast ),并忽略所有KeyDown事件,直到您获得KeyLongPressed事件。

为了获得“正确的” KeyDown事件(你在上一步中忽略的事件),你可以让一个线程检查当前系统时间和tLast (我将它命名为tDelta )之间的时间差是否足够大因为不被认为是连续的新闻。

鉴于在很短的时间内抛出了很多KeyDown事件,理论上可以确定当事件间隔足够时( tDelta大于固定值)没有连续按下音量按钮。

该解决方案的缺点是,如果用户非常快地按下音量按钮( tDelta之间的tDelta低于用于评估连续按压的固定值),则多次按键将被忽略/视为连续键按。

另一个(次要的)缺点是在解释常规按键之前会有一个延迟,因为tDelta必须大于评估你是否正在处理常规或连续按键时使用的固定值。

问候,

卢西恩

编辑:嗯……第二个想法:你不是在使用KeyListener Android实现吗?

如果您正在使用它,请查看为此定义的onKeyUp方法。

如果您只是扩展此类(或其中一个派生类)并使用onKeyUp方法来确定您是否正在处理连续按下(即按钮被按下的时间更长),我认为它会更优雅比固定值)。

如果您可以使用此方法,请执行此操作。 它比上面提到的解决方案更高效,更易于维护和更直接。

KeyListener Javadoc