Flutter InAppWebView:输入框获焦时禁用软键盘
Flutter InAppWebView:输入框获焦时禁用软键盘
嘿,这个需求我之前刚好踩过坑,分享几个实用的方案给你,应该能解决你的问题:
方案一:JS注入 + Flutter端联动(跨平台通用)
这个方案是我最常用的,核心思路是区分输入框聚焦的触发来源——是用户主动触摸,还是扫码程序触发的,然后分别处理:
注入JS监听输入事件
在网页加载完成后,给网页里的所有输入框添加事件监听,标记是否是用户主动触摸触发的聚焦。在InAppWebView的onLoadStop回调里执行这段代码:await controller.evaluateJavascript(source: """ let isUserTouchInitiated = false; // 给所有输入框绑定触摸事件,标记用户主动操作 document.querySelectorAll('input').forEach(input => { input.addEventListener('touchstart', () => { isUserTouchInitiated = true; }); // 监听聚焦事件,根据标记决定是否阻止键盘弹出 input.addEventListener('focus', (e) => { if (!isUserTouchInitiated) { // 非用户触发的聚焦,调用Flutter端方法隐藏键盘 setTimeout(() => { window.flutter_inappwebview.callHandler('hideKeyboard'); }, 0); } // 重置标记,避免影响下一次操作 isUserTouchInitiated = false; }); }); """);Flutter端注册键盘隐藏回调
在onWebViewCreated里给WebView注册一个JS调用的handler,用来接收网页的隐藏键盘请求:controller.addJavaScriptHandler( handlerName: 'hideKeyboard', callback: (args) { // 通过系统通道隐藏软键盘 SystemChannels.textInput.invokeMethod('TextInput.hide'); }, );扫码时的输入处理
当扫码完成后,直接通过JS给目标输入框赋值,哪怕触发聚焦,因为标记是false,也会自动隐藏键盘:// 替换成你的扫码结果和输入框选择器 final scannedBarcode = "123456789"; await controller.evaluateJavascript(source: """ const targetInput = document.querySelector('#your-input-id'); targetInput.value = '$scannedBarcode'; // 如果需要保持输入框聚焦状态 targetInput.focus(); """);
方案二:Android端原生回调控制(仅Android)
如果你的APP只需要适配Android,可以直接用InAppWebView提供的原生回调,更直接:
你需要维护一个标记变量(比如isScanning),扫码前设为true,扫码完成后重置为false,然后在androidOnRequestFocus回调里判断:
InAppWebView( androidOnRequestFocus: (controller, view) async { // 如果是扫码触发的焦点请求,拦截并自己处理,不弹出键盘 if (isScanning) { return true; } // 用户主动触摸的,交给系统处理,弹出键盘 return false; }, // 其他WebView配置... )
这个方案缺点是只支持Android,iOS需要单独处理,所以如果是跨平台项目,还是方案一更稳妥。
方案三:替换为Flutter原生输入框(如果可行)
如果你有权限修改网页内容,或者可以用混合布局把网页里的输入区域换成Flutter的TextField,那控制起来会更简单:
- 把网页输入框换成Flutter的
TextField,默认设置readOnly: true,这样扫码赋值时不会弹出键盘; - 给
TextField添加点击事件,点击时设置readOnly: false并自动弹出键盘,满足用户手动输入的需求。
不过这个方案的前提是你能修改网页布局,要是网页是第三方的没法改,就只能用前两个方案啦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

