一、背景说明
在 Android 应用中,键盘弹出时常会遮挡输入框,尤其是嵌套在 PopupWindow 或 WebView 中的页面,系统并不会自动调整布局高度。这时就需要开发者手动监听键盘状态并动态调整布局,达到“键盘避让”的目的。
二、方案目标
- 动态监听键盘高度变化
- 判断键盘是否弹出
- 根据键盘高度动态调整 WebView 布局
- 支持关闭键盘优化(如部分页面由前端主动抬升)
三、核心思路
- 通过
ViewTreeObserver.OnGlobalLayoutListener获取当前可视区域,监听高度变化。 - 判断当前是否处于键盘弹出状态。
- 若处于弹出状态,根据变化的高度计算
WebView的偏移量(topMargin / bottomMargin)。 - 记录初始布局状态,键盘收起时恢复原始布局。
四、关键变量说明
| 变量名 | 类型 | 说明 |
|---|---|---|
mGlobalLayoutListener | 监听器 | 全局布局监听器 |
mShowingKeyBoard | Boolean | 当前是否处于键盘弹出状态 |
mKeyboardHeight | Int | 当前键盘高度 |
mInitialWebviewTopMargin | Int | WebView 初始 topMargin,用于复原 |
mLastKeyboardOptimizeHeight | Int | 上一次处理的键盘高度,用于防抖 |
mUseKeyboardOptimize | Boolean | 是否开启键盘避让模式 |
五、代码实现
1. 注册监听器:keyboardOptimization()
/**
* 键盘优化 - 记录当前键盘状态,用于在键盘弹出时,不响应手势下滑
*/
private void keyboardOptimization() {
mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
/** 保存键盘调起前的视图 bottom */
int preBottom;
@Override
public void onGlobalLayout() {
Rect rect = new Rect();
mBrowserView.getWindowVisibleDisplayFrame(rect);
// 初次调用,记录底部位置
if (preBottom == 0) {
preBottom = rect.bottom;
return;
}
// 计算当前键盘高度
int keyBoard = preBottom - rect.bottom;
// 键盘状态发生变化
if ((!mShowingKeyBoard && keyBoard > 0) || (mShowingKeyBoard && keyBoard <= 0)) {
mShowingKeyBoard = keyBoard > 0;
mKeyboardHeight = keyBoard;
// 如果关闭优化,并且是弹出键盘,跳过处理
if (!mUseKeyboardOptimize && mShowingKeyBoard) {
return;
}
LogEx.i(TAG, "【键盘高度】mKeyboardHeight = " + mKeyboardHeight);
updateWebViewLayoutParams(mKeyboardHeight);
}
}
};
mRootLayout.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
}2. 更新 WebView 布局:updateWebViewLayoutParams()
/**
* 更新 WebView 布局参数
*
* @param height 抬起高度(键盘高度)
*/
private void updateWebViewLayoutParams(int height) {
LinearLayout.LayoutParams params = getWebViewLayoutParams();
if (params == null) {
return;
}
if (height > 0) {
// 防抖:同样高度不重复处理
if (height == mLastKeyboardOptimizeHeight) {
return;
}
// 记录初始 topMargin
if (mInitialWebviewTopMargin == -1) {
mInitialWebviewTopMargin = params.topMargin;
}
// 计算偏移差值
int delta = height - mLastKeyboardOptimizeHeight;
// 向上抬起 WebView
params.topMargin -= delta;
params.bottomMargin += delta;
} else {
// 键盘收起,恢复原始布局
params.topMargin = mInitialWebviewTopMargin;
params.bottomMargin = 0;
mInitialWebviewTopMargin = -1;
}
// 记录上一次处理高度
mLastKeyboardOptimizeHeight = height;
setWebViewLayoutParams(params);
}更新: 2025-09-03 23:46:48
原文: https://www.yuque.com/dongpozhouzi-mshe3/zhm85g/wbe3beshkp2ax2lq