页面嵌入式View
什么是嵌入式View
在前端开发的过程中,会遇到一些业务场景,使用H5展示用户体验不好,比如地图、股票等内容,在大部分手机上存在拖动不流畅等问题。
针对这些痛点问题,嵌入式View提供了一套Native View嵌入H5页面的解决方案,并为应用层提供了方便灵活的定制方式,让Web应用达到Native同样的用户体验。
为什么选择嵌入式View
关于H5 native化的技术,目前已经有比较流行的Weex、React Native等技术,为什么还要使用嵌入式View的方案呢?
相比Weex等技术,嵌入式View有以下几个优点:
- 非常轻量级。集成于内核中,不需要额外适配,而接入Weex等技术,至少都需要增加几百K的size;
- 使用Html标准语法。前端开发没有学习成本,而且线上已经部署的普通页面可以简单快速修改为支持嵌入式View的页面;
- 安全性高。Weex等技术,因为暴露太多底层功能,可能存在安全性问题,而嵌入式View提供给前端的接口功能单一,安全性较好;
- H5与Native View自然交互。前端页面可以通过内核扩展的js接口、事件、属性等特性与Native View进行自然交互;
- Native View完美融入WebView。体验(滚屏, 缩放等)上感知不到哪些区域是native view。
如何利用嵌入式View进行开发
前端页面写法:
“嵌入式View元素”的定义:
带有 type == application/view 属性的 object 元素。例如下面的object标签,即为一个嵌入式View元素:
<object id="map" type="application/view" width="200" height="100">
<param id="param" name="data" value="origin value"/>
</object>
以上的HTML页面,如果在支持嵌入式View的浏览器,则会创建一个和object标签同样大小及位置的Native View,覆盖在object标签上面,对于普通浏览器,则按照普通object标签进行展示。页面展示效果对比:
同样的页面,不同浏览器展示效果如下:
图1:不支持EmbedView浏览器展示效果
图2:支持EmbedView浏览器展示效果
对于不支持EmbedView的浏览器,展示效果如图1所示,黄色区域(object元素background color 为 yellow)即为object元素;
对于支持EmbedView的浏览器,展示效果如图2所示,黑色区域是一个覆盖于WebView上方的Android TextView,它的大小与位置跟object标签保持一致,并且当页面通过js改变object标签的位置与大小时,Native VIew可以跟随变化。
如何实现嵌入式View效果:
图2的Demo实现非常简单,只要做3件事:
- 前端页面放置一个object标签,并且type="application/view" ,例如上面的HTML示例;
- 浏览器应用层增加一个TestEmbedView类,实现 WebView SDK 提供的 IEmbedView 接口,在 IEmbedView.getView() 方法中返回想要嵌入页面的 View。
- 应用层实现 WebView SDK 提供的 BrowserClient. getEmbedView() 接口,返回实例化的 IEmbedView 对象。
嵌入式View相关能力与接口
WebView SDK 相关类与方法:
类/接口 | 方法 | 版本 | 说明 |
---|---|---|---|
BrowserClient | IEmbedView getEmbedView(EmbedViewParams params, IEmbedViewContainer mController); | EmbedVIew 1.0提供 | BrowserClient扩展的接口,由应用层实现。内核通过该接口获取应用层创建的EmbedView对象 |
EmbedViewConfig | - | 内核向应用层申请EmbedView时传入的相关参数封装 | |
IEmbedViewContainer交互的核心类,提供了相关接口给应用层,应用层也可以设置Listener,接收内核的各种回调通知。 | void notifyEnterFullScreen(); / void notifyExitFullScreen(); | EmbedVIew 1.0提供 | 应用层 EmbedView 进入/退出全屏通知内核 |
void setPosterUrl(String posterUrl); | 规划中 | 应用层 可以通过该接口设置poster image到object元素 | |
void sendViewData(String data); | 规划中 | 应用层 通过该接口传递数据到前端页面 | |
void setXXXListener( XXXListener listerner); | EmbedVIew 1.0提供 | 应用层 设置相关Listener | |
OnParamChangedListener | void onParamChanged(String[] name, String[] value); | 规划中 | 应用层监听Param元素节点的变化:当Object标签内部的Param标签发现变化时,内核通知外壳,并传递相关数据 |
OnStateChangedListener | void onAttachedFromWebView(); / void onDetachedFromWebView(); | EmbedVIew 1.0提供 | 内核将 EmbedView 从view tree 添加 / 移除 前通知应用层 |
void onDestroy() | EmbedVIew 1.0提供 | 内核嵌入式View对象销毁时通知应用层 | |
OnVisibilityChangedListener | void onVisibilityChanged(int reason); | 规划中 | 应用层监听object元素可见性变化,reason的定义:SCROLL_TO_INVISIBLE_AREA:object元素滚出可见区域SCROLL_TO_VISIBLE_AREA:object元素滚入可见区域 |
IEmbedView该类是嵌入式View的抽象,具体由应用层实现 | View getView(); | EmbedVIew 1.1提供 | 由应用层实现。获取EmbedView里面真正的View对象,该View可能是真正展示的View,也可能是展示View的封装。 |
Bitmap getSnapShot(); | EmbedVIew 1.1提供 | 由应用层实现。获取EmbedView内容的截图 |
前端能力增强:
扩展方式 | 具体功能 | 版本 | 说明 |
---|---|---|---|
HTML | 对object标签的type属性进行扩展,增加新类型,用于标识嵌入式View元素。目前有1种type会被识别为嵌入式View:通用嵌入式View:application/view | EmbedVIew 1.0提供 | <object type="application/view" width="500" height="200"><param id="param" name="data" value="xxxxxx" /></object> |
object 元素 poster 属性支持 | EmbedVIew 1.0提供 | 类似video标签的poster属性,支持封面图片的设置 | |
param 标签变化检查 | 规划中 | object标签内部的param数据发生变化时,透传Param数据给外壳 | |
事件 | embedviewopened | EmbedVIew 1.0提供 | EmbedView 创建成功发送embedviewopened消息 |
embedviewclosed | EmbedVIew 1.0提供 | EmbedView 关闭后发送 embedviewclosed消息 | |
error (原有事件扩展) | EmbedVIew 1.0提供 | EmbedView 创建失败 | |
webkitfullscreenchange / webkitfullscreenerror | 规划中 | 全屏事件按照标准流程对接,在EmbedView全屏切换发生相关事件通知页面 | |
JS方法 | object.openView() | 规划中 | js 主动打开nativeView |
object.closeView() | 规划中 | js 主动关闭nativeView | |
webkitRequestFullScreen() | 规划中 | 原生方法对接我们流程,触发EmbedView进入全屏 | |
webkitExitFullscreen() | 规划中 | 原生方法对接我们流程,触发EmbedView退入全屏 | |
JS属性 | embedViewOpened | EmbedVIew 1.0提供 | 查询 EmbedView 是否被打开 |
Document.onfullscreenchange Document.fullscreenElement Document.onfullscreenerror Document.fullscreen | 规划中 | 标准的全屏属性需要跟EmbedView状态对接 |