You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未设置adjustResize时如何获取Android键盘高度?求替代方案

替代方案获取Android键盘高度

Hey,我之前也踩过获取Android键盘高度的兼容性坑——PopupWindow方案和你贴的ViewTreeObserver监听确实在部分定制ROM设备上会失效。给你分享几个我实际项目中验证过的靠谱替代方案:

方案1:使用OnApplyWindowInsetsListener(Android 11+推荐)

Android 11(API 30)之后官方推荐用WindowInsets来处理系统窗口(包括输入法键盘)的变化,这个API直接获取系统提供的Insets数据,避免了计算布局差值带来的误差,在新设备上兼容性拉满。

代码示例:

// 获取Activity的根View
View rootView = getWindow().getDecorView().getRootView();
rootView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
    @Override
    public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
        // 直接获取输入法窗口的高度
        int keyboardHeight = insets.getInsets(WindowInsets.Type.ime()).bottom;
        
        if (keyboardHeight > 100) { // 过滤掉小幅度的布局变动
            isKeyBoardVisible = true;
            changeKeyboardHeight(keyboardHeight);
        } else {
            isKeyBoardVisible = false;
            if (emojiKeyboard.getVisibility() == View.INVISIBLE) {
                emojiKeyboard.setVisibility(View.GONE);
            }
        }
        
        // 必须返回Insets,否则其他相关监听会失效
        return insets;
    }
});

方案2:监听WindowManager全局布局变化(兼容低版本)

如果需要适配Android 11以下的设备,试试监听整个Window的布局变化,比单个View的ViewTreeObserver更不容易受局部布局变动的干扰,在很多定制ROM上表现更稳定。

代码示例:

WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
View decorView = getWindow().getDecorView();

windowManager.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, 
                               int oldLeft, int oldTop, int oldRight, int oldBottom) {
        Rect visibleFrame = new Rect();
        decorView.getWindowVisibleDisplayFrame(visibleFrame);
        int screenHeight = decorView.getRootView().getHeight();
        int keyboardHeight = screenHeight - visibleFrame.bottom;
        
        if (keyboardHeight > 100) {
            isKeyBoardVisible = true;
            changeKeyboardHeight(keyboardHeight);
        } else {
            isKeyBoardVisible = false;
            if (emojiKeyboard.getVisibility() == View.INVISIBLE) {
                emojiKeyboard.setVisibility(View.GONE);
            }
        }
    }
});

方案3:InputMethodManager隐藏API(备选方案)

这个方法用了系统的隐藏API,虽然不是官方推荐,但在某些特殊场景下可以作为兜底方案。不过要注意,不同厂商可能会修改这个API,后续Android版本也可能限制调用,所以建议只在其他方案失效时使用。

代码示例:

InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
try {
    // 调用隐藏方法获取输入法窗口高度
    Method getInputMethodWindowHeight = imm.getClass().getMethod("getInputMethodWindowVisibleHeight");
    int keyboardHeight = (int) getInputMethodWindowHeight.invoke(imm);
    
    if (keyboardHeight > 100) {
        isKeyBoardVisible = true;
        changeKeyboardHeight(keyboardHeight);
    } else {
        isKeyBoardVisible = false;
        if (emojiKeyboard.getVisibility() == View.INVISIBLE) {
            emojiKeyboard.setVisibility(View.GONE);
        }
    }
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
    e.printStackTrace();
    // 兜底到其他方案
}

额外小提示

  • 记得在页面销毁时移除监听,避免内存泄漏:比如ViewTreeObserver监听要调用removeOnGlobalLayoutListener,WindowInsets监听可以设置为null,WindowManager的布局监听要调用removeOnLayoutChangeListener。
  • 有些设备的虚拟导航栏会干扰高度计算,你可以先获取导航栏的高度,再从计算出的差值里减去,避免把导航栏误判为键盘高度。

内容的提问来源于stack exchange,提问作者jack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:54:14