在混合开发场景中,我们经常遇到需要在 WebView 内部动态调整嵌入 iframe 样式的需求。由于 iframe 拥有独立的 DOM 树,直接操作父页面无法触及内部元素,必须通过 JavaScript 注入的方式进入其上下文。
下面是一个完整的 Kotlin 实现方案,重点在于加载时机和跨窗口访问。
1. 基础配置
首先确保 WebView 允许执行 JavaScript。开启后控制台可能会提示 XSS 过滤警告,这是正常的安全机制,不影响功能。
val webView = findViewById<WebView>(R.id.web_wd)
webView.settings.javaScriptEnabled = true
// 如果涉及复杂交互,建议处理 XssFilter 相关设置
2. 注入逻辑
JS 注入必须在页面完全加载后进行,否则目标元素可能尚未渲染。我们重写 onPageFinished 回调,利用 loadUrl("javascript:...") 执行脚本。
关键点在于获取 iframe 的 contentWindow 对象,从而访问其内部的 document。
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
// 页面加载结束,开始注入 JS
val jsCode = """
var iframeBox = document.getElementById('iframe_box');
if (iframeBox && iframeBox.contentWindow) {
var doc = iframeBox.contentWindow.document;
// 定位到具体元素并修改样式
var targetSelect = doc.querySelector('body form table tr td table tbody tr td:nth-of-type(2) select');
var targetDiv = doc.querySelector('body form table tr td table tbody tr td:nth-of-type(1)');
if (targetSelect) targetSelect.setAttribute('style', 'width:80%');
if (targetDiv) targetDiv.setAttribute('style', 'width:20%');
}
""".trimIndent()
view?.loadUrl("javascript:$jsCode")
}
}
3. 注意事项
- 加载顺序:务必在
onPageFinished中调用,避免元素未就绪导致报错。 - 选择器稳定性:示例中的 CSS 选择器非常具体,实际项目中建议结合业务 ID 或类名优化,防止结构变动失效。
- 安全策略:部分 WebView 版本对
javascript:协议有拦截,需确认当前环境支持。

