2012-10-18 25 views
8

我希望我的應用程序對音量按鈕的常規和長按鍵事件作出不同反應。onKeyDown和onKeyLongPress

我已經看到this,但是如果我按住音量按鈕,我會收到很多KeyDown活動,然後我會收到KeyLongPressed事件。

我想要一個事件或另一個事件,而不是兩個事件,以便我可以在短時間內調整音量並在長按下跳過一個音軌。

你能幫我一下嗎?

這是我的代碼:

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

任何幫助表示讚賞! - 虹膜

+0

然後嘗試使用鍵(KeyEvent.KEYCODE_VOLUME_UP)而不是keydown;如果長時間按鍵會在按鍵之前調用,如果長時間按下使用標誌在按鍵上停止動作 – Sandy09

+0

這是音量增大鍵,而不是一個指示器,告訴你鍵被按下或類似的東西。 –

+0

我現在正在嘗試的東西 –

回答

14

這裏是我寫的代碼。它像一個魅力。也許你可以優化它以獲得更好的邏輯。但你會明白這一點。關鍵是使用標誌。 短按是短時間按音量按鈕的新聞,並且發行。所以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 
+1

+1擊敗我一分鐘:)我雖然這樣某種原因,他不會通過鑰匙事件 –

+0

非常感謝你,這個作品很棒! – friday

+0

不客氣! – VendettaDroid

0

我不知道這個答案將提供給您的問題可接受的解決方案,因爲它依賴於得到一個恆定的基礎上頻繁KeyDown事件。

你可以試着記住系統時間時,被拋出的最後一個KeyDown事件(我將其命名爲tLast),而忽略所有KeyDown事件,直到你得到一個KeyLongPressed事件。

爲了得到「正確」 KeyDown事件(您在上一步中忽略了的),你可以有一個線程檢查當前系統時間和tLast之間的時間差(我將其命名爲tDelta)足夠大以至於不被視爲連續出版。

鑑於很多KeyDown事件在短時間內拋出,理論上可以確定當事件間隔足夠時(tDelta大於固定值),音量按鈕並未連續按下。

這種解決方案的缺點是,如果用戶真的很快按下音量按鈕(tDelta之間的壓力低於用於評估連續按壓的固定值),則多次按鍵將被忽略/考慮作爲連續的按鍵。

另一個(次要)短暫的問題是,在解釋常規按鍵之前會有延遲,因爲tDelta將不得不大於評估您是否正在處理常規或連續按鍵時使用的固定值。

問候,

盧西恩

編輯: 嗯......第二個想法:你是不是使用KeyListener Android的實現?

如果您使用此功能,請查看爲此定義的onKeyUp方法。

我認爲如果你只是擴展這個類(或它的派生類之一)並使用onKeyUp方法來確定你是否正在處理連續按鍵(例如按鈕已經壓低大於一個固定值)。

如果您可以使用此方法,請執行此操作。與上述解決方案相比,它更高效,易於維護並且更直接。

KeyListener Javadoc

4

當我正要後我回答我發現有人已經得到了某種解決方案....

但這裏是我的,簡單而且像魅力一樣工作。只有一個標誌;)

這段代碼檢測shortpress和longpress,當longpress發生時,不會觸發shortpress!

注:如果你想正常的音量上下行爲更改onkeypress事件的方法超級調用像這樣的還真:

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

這是更好的答案,因爲它使用較小的變量和助記符代碼。做得好。 – Avijit

3

根據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); 
    } 
} 
+0

更標準,更清潔。我唯一的問題是我的設備在長按之後不久就會發出蜂鳴聲,我通過添加 'else解決了這個問題。else if(keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){ return true; }' to'onKeyUp'。 –