未设置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
相关产品推荐
相关产品推荐

