2015-03-15 2 views
5

Secondo i documenti SDK KeyboardView.OnKeyboardActionListener.onRelease(), "Per le chiavi che si ripetono, viene chiamato solo una volta". Tuttavia, se si imposta IsRepeatable su true per il tasto 'a' con l'esempio Softkeyboard Android e si registrano le chiamate al metodo onPress(), onKey() e onRelease(), ottengo la ripetizione come previsto, ma osservo il seguente registro per una singola sequenza/ripetizione/sequenza di rilascio :Perché Android KeyboardView.OnKeyboardActionListener.onRelease() chiama dopo ogni ripetizione di tasti?

I/SoftKeyboard(31467): onPress: 97 
I/SoftKeyboard(31467): onKey: 97 
I/SoftKeyboard(31467): onRelease: 97 
I/SoftKeyboard(31467): onKey: 97 
I/SoftKeyboard(31467): onRelease: 97 
I/SoftKeyboard(31467): onKey: 97 
I/SoftKeyboard(31467): onRelease: 97 
I/SoftKeyboard(31467): onKey: 97 
I/SoftKeyboard(31467): onRelease: 97 
I/SoftKeyboard(31467): onKey: 97 
I/SoftKeyboard(31467): onRelease: 97 

Come determinare esattamente quando il dispositivo touch è stato rilasciato? Grazie, D.

EDIT (Modifica da Paul Boddington 30/07/2015)

Anche se io non sono il PO, ho voluto inserire un esempio completo che mostra il problema.

MyActivity:

public class MyActivity extends Activity { 

    private static final String TAG = "MyActivity"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_my); 
     KeyboardView keyboardView = (KeyboardView) findViewById(R.id.keyboard_view); 
     keyboardView.setKeyboard(new Keyboard(this, R.xml.keyboard)); 
     keyboardView.setOnKeyboardActionListener(new KeyboardView.OnKeyboardActionListener() { 

      @Override 
      public void onPress(int i) { 
       Log.i(TAG, "onPress: " + i); 
      } 

      @Override 
      public void onKey(int i, int[] ints) { 
       Log.i(TAG, "onKey: " + i); 
      } 

      @Override 
      public void onRelease(int i) { 
       Log.i(TAG, "onRelease: " + i); 
      } 

      @Override public void onText(CharSequence charSequence) {} 
      @Override public void swipeLeft() {} 
      @Override public void swipeRight() {} 
      @Override public void swipeDown() {} 
      @Override public void swipeUp() {} 
     }); 
    } 
} 

keyboard.xml:

<?xml version="1.0" encoding="utf-8"?> 
<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"> 
    android:layout_height="wrap_content" 
    android:layout_width="match_parent" 
    > 
    <Row 
     android:keyWidth="25%p" 
     android:keyHeight="60dp"> 
     <Key android:codes="0" android:keyLabel="0" android:isRepeatable="true"/> 
     <Key android:codes="1" android:keyLabel="1" /> 
     <Key android:codes="2" android:keyLabel="2" /> 
     <Key android:codes="3" android:keyLabel="3" /> 
    </Row> 
</Keyboard> 

activity_my.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <android.inputmethodservice.KeyboardView 
     android:id="@+id/keyboard_view" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:focusable="true" 
     android:focusableInTouchMode="true" 
     /> 
</LinearLayout> 
+0

Immagino che la tua chiave non sia quella che si ripete ... – Marcus

+0

Sì, lo è. Ho chiarito il post originale. – davhoo

+1

Stai usando la tastiera Android di serie? – Zerp

risposta

1

io non riuscivo a capire come risolvere il problema KeyboardView di emettere correttamente la onRelease() per le chiavi ripetibili. Così, invece, mi è venuta in mente una soluzione che riconosca la versione guardando lo MotionEvent.ACTION_UP. Lo fai solo per le chiavi ripetibili e ignora anche gli eventi onRelease() per queste chiavi.

private List<Integer> mRepeatableKeys = new ArrayList<Integer>(); 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    final KeyboardView keyboardView = (KeyboardView) findViewById(R.id.keyboard_view); 
    keyboardView.post(new Runnable() { 
     @Override 
     public void run() { 
      for(Keyboard.Key key : keyboardView.getKeyboard().getKeys()) 
      { 
       if(key.repeatable) mRepeatableKeys.add(key.codes[0]); 
      } 
     } 
    }); 
    keyboardView.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      if (event.getAction() == MotionEvent.ACTION_UP) { 
       if(mTrackingRepeatableKey != -1) 
       { 
        Log.i(TAG, "Repeatable key released: " + mTrackingRepeatableKey); 
        mTrackingRepeatableKey = -1; 
       } 
      } 
      return false; 
     } 
    }); 

    keyboardView.setKeyboard(new Keyboard(this, R.xml.keyboard)); 
    keyboardView.setOnKeyboardActionListener(mKeyboardActionListener); 
} 

private int mTrackingRepeatableKey = -1; 
KeyboardView.OnKeyboardActionListener mKeyboardActionListener = new KeyboardView.OnKeyboardActionListener() { 

    @Override 
    public void onPress(int i) { 
     Log.i(TAG, "onPress: " + i); 
     if(mRepeatableKeys.contains(i)) 
     { 
      mTrackingRepeatableKey = i; 
     } 
    } 

    @Override 
    public void onKey(int i, int[] ints) { 
     if(mRepeatableKeys.contains(i)) 
     { 
      Log.i(TAG, "onKey Repeat: " + i); 
      return; 
     } 
     Log.i(TAG, "onKey: " + i); 
    } 

    @Override 
    public void onRelease(int i) { 
     // Ignore release for repeatable keys 
     if(mRepeatableKeys.contains(i)) return; 
     Log.i(TAG, "onRelease: " + i); 
    } 

    @Override 
    public void onText(CharSequence text) { 
    } 

    @Override 
    public void swipeLeft() { 
    } 

    @Override 
    public void swipeRight() { 
    } 

    @Override 
    public void swipeDown() { 
    } 

    @Override 
    public void swipeUp() { 
    } 
}; 

Testato su Android 5.1. Registri ora letti:

I/MainActivity﹕ onPress: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ onKey Repeat: 1 
I/MainActivity﹕ Repeatable key released: 1 

Se si vuole si può estendere KeyboardView e contengono tutte questa brutta logica all'interno di esso.

+0

Ottima risposta. Ho assegnato la taglia per una soluzione decente. Grazie. Ho fatto un bug report https://code.google.com/p/android/issues/detail?id=181675 –

0

Non eseguo molta programmazione Android, ma non sarebbe semplice controllare se la chiave viene ancora premuta all'interno del metodo onRelease utilizzando il metodo onLongPress?

@Override 
public void onRelease(int i) { 
    if(keyboardView.onLongPress(i){ 
     //do nothing 
    } 
    else{ 
     Log.i(TAG, "onRelease: " + i); 
    } 
} 

Se non mi sbaglio, che il metodo deve restituire un vero se il dito è ancora la chiave e falsa quando ci si ferma.

+1

onLongPress() è un metodo di callback protetto, non si intende richiamarlo esplicitamente. –

+0

Ah sì, nella mia fretta di trovare una soluzione sembra che ho guardato oltre. – Catch44