【发布时间】:2011-12-22 06:46:43
【问题描述】:
我正在尝试检测 Android 中的虚拟键盘高度。
我发现了一个类似的话题:Get the height of virtual keyboard in Android
看来作者找到了一种检测高度的方法:
我找到了获得它的方法。在我请求打开虚拟键盘后,我 发送我生成的指针事件。他们的y坐标从 设备的高度并减小。
我不明白该怎么做。
【问题讨论】:
标签: android events android-softkeyboard
我正在尝试检测 Android 中的虚拟键盘高度。
我发现了一个类似的话题:Get the height of virtual keyboard in Android
看来作者找到了一种检测高度的方法:
我找到了获得它的方法。在我请求打开虚拟键盘后,我 发送我生成的指针事件。他们的y坐标从 设备的高度并减小。
我不明白该怎么做。
【问题讨论】:
标签: android events android-softkeyboard
我将使用您发布的链接中提供的代码:
// Declare Variables
int softkeyboard_height = 0;
boolean calculated_keyboard_height;
Instrumentation instrumentation;
// Initialize instrumentation sometime before starting the thread
instrumentation = new Instrumentation();
mainScreenView 是您的基本视图,您的活动视图。 m(ACTION_DOWN) 和m1(ACTION_UP) 是使用Instrumentation#sendPointerSync(MotionEvent) 调度的触摸事件。逻辑是调度到显示键盘的位置的 MotionEvent 将导致以下SecurityException:
java.lang.SecurityException:注入到另一个应用程序需要 INJECT_EVENTS 权限
因此,我们从屏幕底部开始,在循环的每次迭代中向上(通过递减y)。对于一定数量的迭代,我们将得到一个 SecurityException(我们将捕获它):这意味着 MotionEvent 正在键盘上发生。当y 变得足够小时(当它刚好在键盘上方时),我们将跳出循环并使用以下方法计算键盘的高度:
softkeyboard_height = mainScreenView.getHeight() - y;
代码:
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):
调度一个指针事件。在收件人之后的某个时间完成 已从其事件处理中返回,尽管它可能没有 完全完成对事件的反应——例如,如果它 因此需要更新其显示,它可能仍在 这样做的过程。
【讨论】:
INTERNAL_POINTER_META_STATE 的文档。
INTERNAL_POINTER_META_STATE 是一个整数常量。出于问题的目的,使用任何整数值都可以。我已经编辑了上面的代码。感谢您指出。
1 是否保证始终相同?它是否由 Google 正式记录在任何地方?你能依赖它而不用担心产生脆弱的代码吗?
no。我们指望的 SecurityException 因为缺少权限而被抛出:INJECT_EVENTS。此权限只能通过系统应用程序获得:Romain Guy 确认此here。 Can you rely on this without fear of producing brittle code? 严格来说,这是一个典型的 hack。使用它,但当它松懈时要做好准备。
1 是有面子的。它不参与程序的逻辑。它映射到KeyEvent.META_SHIFT_ON。如果您使用未映射的值感觉更好,请使用零。但我不能推荐一个值,因为它们都只是填充 ...。第六个参数可以采用 KeyEvent.META_X 形式的值。 Shift / alt / ctrl / caps-on 等组成元/修饰键。
使用 OnGlobalLayoutListener,它非常适合我。
【讨论】: