voy a estar utilizando el código proporcionado en el vínculo que has publicado:
// Declare Variables
int softkeyboard_height = 0;
boolean calculated_keyboard_height;
Instrumentation instrumentation;
// Initialize instrumentation sometime before starting the thread
instrumentation = new Instrumentation();
mainScreenView
es su vista base, la vista de su actividad. m
(ACTION_DOWN) y m1
(ACTION_UP) son eventos táctiles que se envían utilizando Instrumentation#sendPointerSync(MotionEvent)
. La lógica es que un MotionEvent enviado a donde el teclado se está mostrando hará que el siguiente SecurityException
:
java.lang.SecurityException: La inyección a otra aplicación requiere el permiso INJECT_EVENTS
Por lo tanto, comenzamos en la parte inferior de la pantalla y hacer nuestro camino hacia arriba (disminuyendo y
) en cada iteración del ciclo. Para cierto número de iteraciones, obtendremos una SecurityException (que captaremos): esto implicaría que MotionEvent está sucediendo a través del teclado. En el momento en y
consigue bastante pequeña (cuando su justo encima del teclado), vamos a romper fuera del circuito y calculamos la altura del teclado usando:
softkeyboard_height = mainScreenView.getHeight() - y;
Código:
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)
:
Despachar un evento de puntero. Finalizado en algún momento después de que el destinatario haya regresado de su procesamiento de eventos, aunque puede no haber terminado reaccionando desde el evento; por ejemplo, si necesita actualizar su pantalla como resultado, aún puede estar en el proceso de hacer eso.
¿Esto es una API pública? No puedo encontrar documentación sobre 'INTERNAL_POINTER_META_STATE'. – rid
@rid Disculpa por eso. 'INTERNAL_POINTER_META_STATE' es una constante entera. Para el propósito de la pregunta, usar cualquier valor entero funcionaría. He editado el código de arriba. Gracias por mencionarlo. – Vikram
Aún así, ¿es seguro usar esto sin que la funcionalidad tenga la posibilidad de desaparecer en ninguna versión futura de Android? ¿Ese '1' garantiza que siempre será el mismo? ¿Está documentado oficialmente en Google por Google? ¿Puedes confiar en esto sin temor a producir código frágil? – rid