在Android中获取虚拟键盘的高度

15

我如何在安卓系统中获取虚拟键盘的高度?这是否可能?

我尝试从主窗口中获取它,但是它给出了整个应用程序的完整高度。我想获取键盘的高度。


软键盘并不是唯一可以占用屏幕空间的系统提供的装饰。您打算如何处理这个尺寸? - adamp
我想在软件虚拟键盘上方绘制一些图像。我正在开发2D应用程序,因此不使用Android UI库。例如,我想在软键盘顶部绘制边框。 - Adem
1
虚拟键盘不会将窗口向上推吗? 如果是这样,您只需要在屏幕底部画一条顶部边框线(在软键盘激活之前设置为不可见)。 - keyser
只有在窗口不是全屏状态下,它才会将窗口向上推。 - Ronnie
请看我的答案这里 - Jan Rozenbajgier
6个回答

4

您无法获取键盘高度,但是您可以获取视图的高度,这才是您真正想要的 - 并且您将在 onLayout 调用中向当前视图提供此数据。


4
我的视图显示了整个设备的高度。因此,这个信息并不包括虚拟键盘的高度。但是,我找到了一种获取它的方法。在我请求打开虚拟键盘后,我发送一个我生成的指针事件。它们的y坐标从设备的高度开始减少。然后,当指针事件在虚拟键盘上时,系统会抛出异常。如果这些指针事件不在虚拟键盘上,就不会有异常。因此,我可以得到虚拟键盘的高度。 - Adem
这是针对带有导航栏的Android型号吗? - user5698345

1

你可以使用这个示例代码。虽然不太优美,但它能正常工作。

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,
                            INTERNAL_POINTER_META_STATE);
                    final MotionEvent m1 = MotionEvent.obtain(
                            SystemClock.uptimeMillis(),
                            SystemClock.uptimeMillis(),
                            MotionEvent.ACTION_UP,
                            x, 
                            y,
                            INTERNAL_POINTER_META_STATE);
                    boolean pointer_on_softkeyboard = false;
                    try {
                        getSingletonInstrumentation().sendPointerSync(m);
                        getSingletonInstrumentation().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;
                        }
                        break;
                    }
                    y--;

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

INTERNAL_POINTER_META_STATE在哪里?metaState是指KeyEvent API:http://developer.android.com/reference/android/view/KeyEvent.html#getMetaState(),但是找不到INTERNAL_POINTER_META_STATE。 - lordhong
INTERNAL_POINTER_META_STATE 只是一个标识此事件源的ID,因此您可以跟踪是由您还是设备生成的指针事件。您只需将整数值设置为 INTERNAL_POINTER_META_STATE。 - Adem
4
getSingletonInstrumentation() 方法是什么? - yahya

1
假设您的布局的根视图是RelativeLayout。 您可以创建一个扩展了RelativeLayout并重写了onSizeChanged方法的CustomRelativeLayout类。 因此,当软键盘弹出时,RelativeLayout的高度将发生变化,并且变化将在onSizeChanged方法中得到通知。
public class CustomRelativeLayout extends RelativeLayout {

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    int softKeyboardHeight = oldh - h; // Assuming softKeyboard Opened up
    // oldh is the height when the layout was covering the whole screen
    // h is the new height of the layout when the soft keyboard opened up

    if(softKeyboardHeight > oldh * 0.15) {
        Log.i("Here", Integer.toString(softKeyboardHeight));
        // Keyboard has popped up

    } else {
        // Not the keyboard
    }
}

在您的清单文件中进行以下更改,以便 Activity 以 Resize 模式而非平移和扫描模式打开。在 Resize 模式下,当键盘弹出时,布局将能够调整大小。 要了解有关平移扫描和 Resize 的更多信息,请访问https://developer.android.com/training/keyboard-input/visibility
<activity
        android:name=".MainActivity"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

1
这个解决方案也有些hacky,但解决了问题(至少对我而言)。
  1. 我在屏幕底部放置了一个透明背景的临时视图,因此这个视图将是不可见的。
  2. 我在清单文件中的活动标记中添加了 android:windowSoftInputMode="adjustResize" 标志。
  3. 现在主要的故事在于 onGlobalLayout()。在那里,我计算了临时视图和根视图高度之间的 y 轴差异

    final View view = findViewById(R.id.base); view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
    
        int rootViewHeight = view.getRootView().getHeight();
        View tv = findViewById(R.id.temp_view);
        int location[] = new int[2];
        tv.getLocationOnScreen(location);
        int height = (int) (location[1] + tv.getMeasuredHeight());
        deff = rootViewHeight - height;
        // deff 是软键盘的高度
    
    }
    

    });


1

如果你的应用不需要 android:windowSoftInputMode="adjustResize",那么你可以尝试这样做:

    any_view.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            int height = main_layout.getHeight();
            Log.w("Foo", String.format("layout height: %d", height));
            Rect r = new Rect();
            main_layout.getWindowVisibleDisplayFrame(r);
            int visible = r.bottom - r.top;
            Log.w("Foo", String.format("visible height: %d", visible));
            Log.w("Foo", String.format("keyboard height: %d", height - visible));
        }
    });

1
getWindowVisibleDisplayFrame 对我不起作用,它返回的是视图的高度。 - Dominic D'Souza

0

试试这个

KeyboardView keyboardView = new KeyboardView(getApplicationContext(), null);
int height = (keyboardView.getKeyboard()).getHeight();
Toast.makeText(getApplicationContext(), height+"", Toast.LENGTH_LONG).show();

1
看起来非常简单,只有两行代码...但对我不起作用。keyboardView.getKeyboard()返回null - Dirk
我也一样...keyboardView.getKeyboard()返回null。 - Ganesh Kanna
如果您不需要监听器,使用这个可能会更好,虽然可能不太准确。 - Beraki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接