onKeyDown and onKeyLongPress
Here is the code that I wrote. It works like a charm. May be you can optimize it for better logic. But you will get the point with it. The key is to use flags. Short press is a press where we press volume button for short time and release. So onKeyUp is the one which will help us detect short presses.
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 for all long presses(No short press detected):
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 for all short presses:
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
Trying to catch the Volume onKeyLongPress() not working
You are almost there. You need to detect the same key event in the onKeyPress handler and start tracking it so that the long press can work. Here's the code you need:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
event.startTracking();
return true;
}
return super.onKeyDown(keyCode, event);
}
onKeyLongPress not working for KeyboardKey
For soft keyboard, you should use proper timer to handle long press event like any other applications. LatinIME also uses this solution, please check out.
PointerTracker.onDownEventInternal.startLongPressTimer()
Android onKeyLongPress when webview exists
You need to override the onBackPressed()
method instead of onKeyDown()
, which is called from onKeyUp()
post-Eclair unless the target SDK is set to lower than Eclair. Returning true
from onKeyLongPress()
will cause the event to be cancelled, and onBackPressed()
won't be called.
@Override
public void onBackPressed() {
if(mWebView.canGoBack()) {
mWebView.goBack();
} else {
super.onBackPressed();
}
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
&& !event.isCanceled() {
super.onBackPressed();
return true;
}
return false;
}
Edit: Actually you should override the onKeyUp()
method instead to provide the same experience, and set a flag on the onKeyLongPress()
call to check if it has been long pressed:
private boolean isBackKeyLongPressed;
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
&& !event.isCanceled()) {
if (!isBackKeyLongPressed && mWebView.canGoBack()) {
mWebView.goBack();
} else {
onBackPressed();
}
isBackKeyLongPressed = false;
return true;
}
if (keyCode == KeyEvent.KEYCODE_BACK) {
isBackKeyLongPressed = false;
}
return super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && !event.isCanceled()) {
isBackKeyLongPressed = true;
}
return false;
}
Android onKeyLongPress
Ok, I have found a solution. Not the best, but it works.OnKeyDown
and OnKeyLongPress
are still the same, but OnKeyUp
is now this:
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if(!event.isCanceled()){
switch(keyCode){
case KeyEvent.KEYCODE_VOLUME_UP:
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
break;
}
}
return super.onKeyUp(keyCode, event);
}
How to differentiate between long key press and regular key press?
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:
- Before you return true, call
event.startTracking()
as explained in the documentation. - 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 );
}
Related Topics
Android - Nestedscrollview Which Contains Expandablelistview Doesn't Scroll When Expanded
Android - Build Separate APKs for Different Processor Architectures
Android Emulator Not Receiving Push Notifications
Android SQLite Selection Args[] with Int Values
Could Not Launch Emulator in Android Studio
Add a New Item to Recyclerview Programmatically
Find the Key Hash for a Signed App
Create a Chatview Layout in Android
Why There's a Separate Mutablelivedata Subclass of Livedata
How to Parse the CSV File in Android Application
How to Use Sharedpreferences to Save More Than One Values
Ndk: How Include *.So Files in Androidstudio
Calledfromwrongthreadexception
Using the "Animated Circle" in an Imageview While Loading Stuff