2011-12-22 10 views

risposta

3

sarò utilizzando il codice fornito al link che hai postato:

// Declare Variables 

int softkeyboard_height = 0; 
boolean calculated_keyboard_height; 
Instrumentation instrumentation; 

// Initialize instrumentation sometime before starting the thread 
instrumentation = new Instrumentation(); 

mainScreenView è la vostra vista di base, punto di vista di vostra attività. m (ACTION_DOWN) e m1 (ACTION_UP) sono eventi di tocco che vengono inviati utilizzando Instrumentation#sendPointerSync(MotionEvent). La logica è che un MotionEvent inviato al punto in cui la tastiera viene visualizzata causerà la seguente SecurityException:

java.lang.SecurityException: Iniezione a un'altra applicazione richiede l'autorizzazione INJECT_EVENTS

Quindi, iniziamo nella parte inferiore dello schermo e risalire (decrementando) su ogni iterazione del ciclo. Per un certo numero di iterazioni, otterremo una SecurityException (che cattureremo): ciò implicherebbe che MotionEvent si verifichi sulla tastiera. Nel momento in cui y ottiene abbastanza piccolo (quando il suo appena sopra la tastiera), ci spezziamo fuori dal giro e calcoliamo l'altezza della tastiera:

softkeyboard_height = mainScreenView.getHeight() - y; 

Codice:

Thread t = new Thread(){ 
     public void run() { 
      int y = mainScreenView.getHeight()-2; 
      int x = 10; 
      int counter = 0; 
      int height = y; 
      while (true){ 
       final MotionEvent m = MotionEvent.obtain(
         SystemClock.uptimeMillis(), 
         SystemClock.uptimeMillis(), 
         MotionEvent.ACTION_DOWN, 
         x, 
         y, 
         1); 
       final MotionEvent m1 = MotionEvent.obtain(
         SystemClock.uptimeMillis(), 
         SystemClock.uptimeMillis(), 
         MotionEvent.ACTION_UP, 
         x, 
         y, 
         1); 
       boolean pointer_on_softkeyboard = false; 
       try { 
        instrumentation.sendPointerSync(m); 
        instrumentation.sendPointerSync(m1); 
       } catch (SecurityException e) { 
        pointer_on_softkeyboard = true; 
       } 
       if (!pointer_on_softkeyboard){ 
        if (y == height){ 
         if (counter++ < 100){ 
          Thread.yield(); 
          continue; 
         } 
        } else if (y > 0){ 
         softkeyboard_height = mainScreenView.getHeight() - y; 
         Log.i("", "Soft Keyboard's height is: " + softkeyboard_height); 
        } 
        break; 
       } 
       y--; 

      } 
      if (softkeyboard_height > 0){ 
       // it is calculated and saved in softkeyboard_height 
      } else { 
       calculated_keyboard_height = false; 
      } 
     } 
    }; 
    t.start(); 

Instrumentation#sendPointerSync(MotionEvent):

Invia un evento puntatore. Finito in qualche momento dopo che il destinatario è tornato dall'elaborazione dell'evento, anche se potrebbe non avere completamente finito di reagire dall'evento - ad esempio, se lo ha bisogno di aggiornare la sua visualizzazione come risultato, potrebbe essere ancora nel processo di farlo.

+0

È un'API pubblica? Non riesco a trovare la documentazione su 'INTERNAL_POINTER_META_STATE'. – rid

+0

@rid Scusaci. 'INTERNAL_POINTER_META_STATE' è una costante intera. Per lo scopo della domanda, l'utilizzo di qualsiasi valore intero potrebbe funzionare. Ho modificato il codice sopra. Grazie per segnalarlo. – Vikram

+0

Ancora, è sicuro usare questo senza che la funzionalità abbia la possibilità di sparire in qualsiasi versione futura di Android? È garantito che '1' sia sempre lo stesso? È documentato ovunque da Google ufficialmente? Puoi fare affidamento su questo senza paura di produrre codice fragile? – rid

1

Utilizzare OnGlobalLayoutListener, funziona perfettamente per me.

Problemi correlati