2012-10-18 14 views
8

Desidero che la mia applicazione reagisca in modo diverso a un evento chiave normale e prolungato dei pulsanti del volume.onKeyDown e onKeyLongPress

Ho già visto this, ma se tengo premuto il pulsante del volume, ricevo un sacco di eventi KeyDown prima di ottenere l'evento KeyLongPressed.

Mi piacerebbe avere un evento o l'altro, non entrambi, in modo da poter regolare il volume con una pressione breve e saltare un brano con una pressione prolungata.

Potete aiutarmi qui?

Questo è il mio codice:

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

Qualsiasi aiuto apprezzato! - Iris

+0

quindi provare con key up (KeyEvent.KEYCODE_VOLUME_UP) anziché keydown; se premere a lungo chiamerà prima della chiave, se premuto a lungo chiamato interromperà l'azione in keyup usando la flag – Sandy09

+0

Questa è la chiave di aumento del volume, non un indicatore che indica che la chiave è premuto o qualcosa del genere. –

+0

Sto provando le cose al momento –

risposta

14

Ecco il codice che ho scritto. Esso funziona magicamente. Potrebbe essere possibile ottimizzarlo per una migliore logica. Ma otterrai il punto con questo. La chiave è usare le bandiere. Breve pressione è una stampante in cui si preme il pulsante del volume per breve tempo e rilasciare. Quindi onKeyUp è quello che ci aiuterà a rilevare le brevi pressioni.

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 per tutti i lunghi presse (No breve pressione rilevato):

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 per tutti i brevi pressioni:

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 Mi picchia per un minuto :) I though that for for qualche ragione per cui non sarebbe passato gli eventi key up –

+0

grazie mille, funziona alla grande! – friday

+0

Siete i benvenuti !!! – VendettaDroid

0

Non so se questa risposta fornirà una soluzione accettabile per il vostro problema, in quanto ha basa su come ottenere frequentiKeyDown eventi su una base costante.

Si potrebbe provare a ricordare l'ora di sistema quando viene generata l'ultima KeyDown evento (I assegniamo il nome tLast), e ignorare tutte le KeyDown gli eventi fino ad ottenere un evento KeyLongPressed.

Al fine di ottenere le "giuste" KeyDown eventi (quelli ignorato nel passaggio precedente), si potrebbe avere un filo controllando se la differenza di tempo tra l'ora corrente del sistema e tLast (io lo chiama tDelta) è abbastanza grande da non essere considerato una stampa continua.

Dato che un sacco di KeyDown eventi vengono gettati in un breve periodo di tempo, si potrebbe teoricamente determinare il tasto del volume non è stato premuto in modo continuo quando gli eventi sono distanziati abbastanza (tDelta è superiore ad un valore fisso).

Lo svantaggio di questa soluzione è che, se l'utente preme il pulsante del volume molto velocemente (tDelta tra le presse è inferiore al valore fisso utilizzato per valutare una stampa continua), i tasti multipli verranno ignorati/considerati come una pressione dei tasti continua.

Un altro (minore) ritardo è che ci sarebbe un ritardo prima di interpretare le normali pressioni dei tasti, poiché tDelta dovrebbe essere maggiore del valore fisso utilizzato quando si valuta se si ha a che fare con una pressione di tasto normale o continua .

saluti,

Lucian

EDIT: Hmm ... secondo pensiero: Non sei utilizza uno Android implementazione KeyListener?

Se si utilizza questo, controllare il metodo onKeyUp definito per questo.

Penso che sarebbe più elegante se estendessi semplicemente questa classe (o una delle sue classi derivate) e usassi il metodo onKeyUp per determinare se hai a che fare con una macchina da stampa continua (cioè l'ora in cui il pulsante è stato tenuto premuto è maggiore di un valore fisso).

Se è possibile utilizzare questo metodo, si prega di farlo. È anche più efficiente, più facile da mantenere e più semplice del work-around presentato sopra.

KeyListener Javadoc

4

Quando ero in procinto di pubblicare la mia rispondo ho scoperto che qualcuno ha già una soluzione ...

Ma qui è mio, semplice e funziona come un fascino. Un solo flag;)

Questo codice rileva le operazioni di compressione e pressione prolungata, in caso di pressione prolungata non viene eseguito alcun intervento di stampa!

Nota: se si desidera che il volume normale e comportamento giù cambiano il ritorno vero nel metodo OnKeyPress alla chiamata super come questo:

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

codice senza il super chiamata:

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

codice qui è con il tasto volume su aggiunto, basta scegliere il vostro lato;)

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

Questa è la risposta migliore, poiché utilizza variabili minori e codice mnemonico. Molto bene. – Avijit

3

Modo corretto in base all'SDK per gestire le lunghe pressioni dei pulsanti.

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

Molto più standard e molto più pulito.Il mio unico problema era che il mio dispositivo emetteva un beep poco dopo la lunga pressione, che ho risolto aggiungendo 'else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { return true; } ' a' onKeyUp'. –