在 Android 开发
中,许多时候不可避免需要展示 富文本
内容,通常我们用到 WebView 加载网页的形式来实现,比如新闻类应用的新闻详情页、休闲软件的阅读界面等等,几乎你看到的图文混杂的富文本页面都是由网页实现的。
但不知道读者有没有发现,这些网页和 Native 交互起来很自然,完全不像网页。比如点击网页的图片跳转到图片浏览界面、标题预加载图片懒加载,包括我司阅读软件的阅读界面的点击查词。本文将讲述如何通过 JavaScript 处理 HTML 的 DOM 结构来实现与 Native 更好地交互。
1. 概览
1.1 DOM 是什么
DOM(Document Object Model)是浏览器加载网页时构造的对象树结构,如图:
HTML 本身也是 XML 格式,熟悉 XML 解析的读者对这个可能并不陌生,每一个标签都被抽象为一个 Element,它具备它包含的文本和它具有的属性。
1.2 JavaScript 能对其做什么
JavaScript 获得了足够的能力来创建动态的 HTML:
- JavaScript 能够改变页面中的所有 HTML 元素
- JavaScript 能够改变页面中的所有 HTML 属性
- JavaScript 能够改变页面中的所有 CSS 样式
- JavaScript 能够对页面中的所有事件做出反应
1.3 三种取得 HTML 元素的方法
(1)通过 id 查找
1 | var x=document.getElementById("intro"); |
(2)通过标签名查找
1 | var x=document.getElementsByTagName("p"); |
(3)通过 class 查找
1 | var x=document.getElementsByClassName('cc') |
1.4 操作 HTML 元素
(1)改变 HTML 输出流
在 JavaScript 中,document.write() 可用于直接向 HTML 输出流写内容,注意会覆盖网页现有内容
(2)改变 HTML 内容
修改 HTML 内容的最简单的方法时使用 innerHTML 属性,例如:
1 | <html> |
(3)改变 HTML 属性
Element#attributeName = value 语法用来改变 HTML 元素的属性,例如:
1 |
|
1.5 操作 CSS 元素
Element#style.propertyName = newStyle 语法用来改变样式,例如:
1 | <h1 id="id1">My Heading 1</h1> |
1.6 DOM 事件
HTML DOM 使 JavaScript 有能力对 HTML 事件做出反应,如:
- 当用户点击鼠标时
- 当网页已加载时
- 当图像已加载时
- 当鼠标移动到元素上时
- 当输入字段被改变时
- 当提交 HTML 表单时
- 当用户触发按键时
此处讲述点击事件,其他事件类似,可前往 W3School 参考
(1)HTML 声明事件
1 | <h1 onclick="this.innerHTML='谢谢!'">请点击该文本</h1> |
(2)JS 添加事件
1 | document.getElementById("myBtn").onclick=function(){ |
1.7 添加和删除
(1)创建新的 HTML 元素
1 | <div id="div1"> |
(2)删除已有的 HTML 元素
1 | <div id="div1"> |
父节点可通过 parentNode 属性寻找到,如上述代码可以简单实现:
1 | var child=document.getElementById("p1"); |
2. 应用
在 Android 中,应用思路主要是通过执行 JavaScript 代码为网页 DOM 添加事件,回调我们的 Native 接口,此处以为网页添加单词点击事件为例。
2.1 第一步,分析网页
后端接口返回的 JSON 数据中,其中需要我们展示的便是这段 HTML 代码,我们的目的是为每个单词添加点击事件。
1 | <div class="paragraph" id="para_2"> |
简单分析很容易发现,每一个单词都是一个 span 标签,或者 class 都为 “span”,而且我们需要展示的内容全部都在标签属性中体现了,所以我们选择 span 标签下手。
2.2 第二步,准备添加点击的 JS 代码
JS 代码很简单,找出所有的 span 标签元素,为每个标签元素添加 onclick 事件属性即可:
1 | var tags = document.getElementsByTagName('span') |
接下来,在 Native 端我们要在网页加载完毕后执行这段代码:
1 | private class DetailWebClient extends WebViewClient { |
2.3 第三步,声明 Native 接口
通过 WebView 的 addJavascriptInterface() 方法可指定接口,代码如下:
1 | webview.addJavascriptInterface(this, "detail"); |
总结
本文主要讲解了 WebView 是如何与网页更好交互的,通常的手段是执行 JavaScript 代码操作 DOM,为 HTML 元素添加点击事件,而在事件中回调 Native 实现的。