沉浸式webview输入框被输入法遮挡了怎么办?!

还是那个倒霉的双十一需求,测试时发现发弹幕的输入框被系统输入法挡住了,这个问题在之前UC内核的浏览器时没问题啊。经过各种对比定位,发现是因为这次需求还有个沉浸式的实现,就是这个实现导致输入框无法被弹起。所幸看到了AndroidBug5497Workaround (用我这个就够了)这篇blog,试验后效果拔群,唯独有个小遗憾是没有适配非沉浸式的状态,沉浸式和非沉浸式切换时会有个小黑条。小子不才遂在大神肩膀上狗尾续貂,以资来者。

原理

网传这是个Android固有的bug,具体原理我也没搞明白了,秉着又不是不能用的原则,先把问题解决了。

这个实现主要就是在键盘出现和消失的时候计算键盘、状态栏以及导航栏的高度,以便确定页面太高的大小。我的小调整就是增加一个沉浸式状态的传递,如果是沉浸式则需要少减一个状态栏的高度,仅此而已。

实现

Java代码
java 复制代码
public class AndroidBug5497Workaround {
	// For more information, see https://issuetracker.google.com/issues/36911528
	// To use this class, simply invoke assistActivity() on an Activity that already has its
	// content view set.

	public static void assistActivity(Activity activity, boolean isImmersive) {
		new AndroidBug5497Workaround(activity, isImmersive);
	}

	private View mChildOfContent;
	private int usableHeightPrevious;
	private FrameLayout.LayoutParams frameLayoutParams;

	private boolean isImmersive;

	private AndroidBug5497Workaround(Activity activity, boolean isImmersive) {
		FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
		mChildOfContent = content.getChildAt(0);
		mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
			public void onGlobalLayout() {
				possiblyResizeChildOfContent();
			}
		});
		frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
		this.isImmersive = isImmersive;
	}

	private int frameLayoutHeight = 0;

	private void possiblyResizeChildOfContent() {
		int usableHeightNow = computeUsableHeight();
		if (usableHeightNow != usableHeightPrevious) {
			int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
			int heightDifference = usableHeightSansKeyboard - usableHeightNow;
			if (heightDifference > (usableHeightSansKeyboard / 4)) {
				// keyboard probably just became visible
				frameLayoutHeight = frameLayoutParams.height;// !!!修改前保存原有高度
				// 是否沉浸式,增减状态栏高度
				int statusBarHeight = isImmersive && BarUtil.isSupportFitsSystem() ?
						BarUtils.getStatusBarHeight() : 0;
				frameLayoutParams.height = usableHeightSansKeyboard - heightDifference + statusBarHeight;
			} else {
				// keyboard probably just became hidden
				if (0 != frameLayoutHeight) {
					frameLayoutParams.height = frameLayoutHeight;// !!!收起键盘恢复原有高度
				}
			}
			mChildOfContent.requestLayout();
			usableHeightPrevious = usableHeightNow;
		}
	}

	private int computeUsableHeight() {
		Rect r = new Rect();
		mChildOfContent.getWindowVisibleDisplayFrame(r);
		return (r.bottom - r.top);
	}
}

在初始化webview的onCreate()方法中增加一句即可

复制代码
AndroidBug5497Workaround.assistActivity(this, isImmersive);

参考

AndroidBug5497Workaround (用我这个就够了)

相关推荐
StackNoOverflow15 分钟前
MySQL Explain 返回列详解:从入门到实战,附 SQL 与避坑大全
android
CYRUS_STUDIO9 小时前
Frida 检测与对抗实战:进程、maps、线程、符号全特征清除
android·逆向
csj5010 小时前
安卓基础之《(28)—Service组件》
android
lhbian12 小时前
PHP、C++和C语言对比:哪个更适合你?
android·数据库·spring boot·mysql·kafka
catoop13 小时前
Android 最佳实践、分层架构与全流程解析(2025)
android
ZHANG13HAO13 小时前
Android 13 特权应用(Android Studio 开发)调用 AOSP 隐藏 API 完整教程
android·ide·android studio
田梓燊14 小时前
leetcode 142
android·java·leetcode
angerdream14 小时前
Android手把手编写儿童手机远程监控App之JAVA基础
android
菠萝地亚狂想曲14 小时前
Zephyr_01, environment
android·java·javascript
sTone8737515 小时前
跨端框架通信机制全解析:从 URL Schema 到 JSI 到 Platform Channel
android·前端