【问题标题】:how can i get soft keyboard height on android?如何在 android 上获得软键盘高度?
【发布时间】:2024-01-21 12:05:01
【问题描述】:

这些天来,我一直在使用 libgdx 开发一个 android 项目。期间出现了一个问题。当软键盘出现时,一些视图会被覆盖,所以我想得到解决这个错误的高度。

我知道在使用android api开发项目时可以设置软输入模式来解决这个问题,libgdx有没有提供什么方法​​?

【问题讨论】:

标签: android libgdx android-softkeyboard


【解决方案1】:

我想分享一个可行的解决方案。

首先,没有办法从 libgdx api 中获取软键盘高度。您必须编写特定于平台的代码。与平台特定代码的接口相当简单——不用担心! Read this guide from the official libgdx wiki.

以下代码是原生android代码,应该放在libgdx android gradle模块中:

import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import com.badlogic.gdx.backends.android.AndroidApplication;

/**
 * Container for platform-specific android implementation.
 */
public class PlatformSpecificAndroidImpl implements PlatformSpecificService {
    private AndroidApplication androidApplication;
    private AndroidGlobalLayoutListener globalLayoutListener;

    public PlatformSpecificAndroidImpl(AndroidApplication androidApplication) {
        this.androidApplication = androidApplication;
    }

    /**
     * Initialize platform services. This method should be called from the gdx applications "create()" method.
     */
    @Override
    public void init() {
        globalLayoutListener = new AndroidGlobalLayoutListener(androidApplication);
        Window window = androidApplication.getWindow();
        if (window != null) {
            View decorView = window.getDecorView();
            if (decorView != null) {
                View rootView = decorView.getRootView();
                if (rootView != null) {
                    ViewTreeObserver viewTreeObserver= rootView.getViewTreeObserver();
                    if (viewTreeObserver != null) {
                        viewTreeObserver.addOnGlobalLayoutListener(globalLayoutListener);
                    }
                }
            }
        }
    }

    /**
     * Get the window height that is really usable, subtracting the soft-keyboard if open.
     * @return usable window height
     */
    @Override
    public int getUsableWindowHeight() {
        if (globalLayoutListener != null) {
            return globalLayoutListener.getHeight();
        }
        return 0;
    }

    private static class AndroidGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
        private AndroidApplication androidApplication;
        private int height;

        private AndroidGlobalLayoutListener(AndroidApplication androidApplication) {
            this.androidApplication = androidApplication;
        }

        @Override
        public void onGlobalLayout() {
            height = 0;
            Window window = androidApplication.getWindow();
            if (window != null) {
                View currentFocus = window.getCurrentFocus();
                if (currentFocus != null) {
                    View rootView = currentFocus.getRootView();
                    if (rootView != null) {
                        Rect rect = new Rect();
                        rootView.getWindowVisibleDisplayFrame(rect);
                        height = rect.bottom;
                    }
                }
            }
        }

        public int getHeight() {
            return height;
        }
    }
}

现在,您可以在 libgdx 核心模块中通过 PlatformSpecificService 接口调用方法 getUsableWindowHeight()。它返回显示高度(以像素为单位)减去软键盘高度。

为什么我在请求时使用了 OnGlobalLayoutListener 而不是直接在 getter 方法中计算高度?好吧,在我看来,这种方式是一个稍微优雅的解决方案。

还有一个问题需要注意: 通过Gdx.input.setOnscreenKeyboardVisible(true);打开软键盘涉及异步通信。如果你碰巧在 setOnscreenKeyboardVisible 之后直接调用getUsableWindowHeight(),你仍然会得到完整的显示高度,因为键盘还没有真正打开。

【讨论】:

    【解决方案2】:

    是的,您可以在 Viewtree Observer 和全局布局监听器的帮助下,尝试以下提到的步骤

    1. 获取布局的根视图
    2. 获取该根的 Viewtree 观察者,并在其之上添加一个全局布局侦听器。

    现在,每当显示软键盘时,android 都会重新调整您的屏幕大小,并且您会收到听者的呼叫。这就是您现在需要做的唯一一件事是计算您的根视图在重新调整大小后的高度与原始大小之间的差异。如果差值大于 150,则认为这是键盘已充气。

    下面是示例代码

    root.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){
         public void onGlobalLayout(){
               int heightDiff = root.getRootView().getHeight()- root.getHeight();
               // IF height diff is more then 150, consider keyboard as visible.  
            }
      });
    

    【讨论】:

    • thanx,我已经尝试过您上面提到的这种方式,但似乎没有任何改变。软键盘显示时,不调用 onGlobalLayout() 函数
    • 这不会给你键盘的高度。