前言
WebView同层渲染,并不是一个新技术,国内一线互联网产品广泛应用,比如小程序的原生组件,电商H5嵌原生播放器等场景;
场景分析 | 技术博客 |
---|---|
微信小程序 | 小程序同层渲染原理剖析 |
百度小程序 | 【走进小程序原理】揭秘组件同层渲染 |
淘宝系播放器 | 618淘系前端技术分享 |
如果您了解其原理,会发现这玩意在Android端,需要修改浏览器内核才能搞定,所以上手难度高;以至于读完文章,心血澎湃直呼牛逼,但是回过头翻看原生WebView代码,并没有找到合适的API;
同层渲染简介
在Android平台,H5内容依托WebView视图渲染,它和原生的View是独立平等的关系, 从绘制层次上来看,WebView和原生必然存在相互覆盖遮挡的,更没法做到同步滚动;
在网页DOM树中,间杂一部分原生的组件,且保留原本的层次和样式,这就是同层渲染;
同层渲染能解决什么问题?
使用web前端技术实现困难,或者稳定性、性能受限等情况
例如:视频播放器、地图、游戏引擎、直播推拉流、摄像头预览等场景;
领略X5内核浏览器同层渲染
准备工作:
- 正确接入腾讯X5浏览器 x5.tencent.com/
- 保证X5内核加载成功 x5.tencent.com/docs/questi…
准备一个占位标签
X5同层渲染的原理是用原生接管在H5页面里的特定标签,所以得准备一个H5页面,然后插入一个自定义的标签, 标签名可以随意定义,比如mytag,样式就按照标准的css来设置
<mytag id = "mytag" src="https://vfx.mtime.cn/Video/2019/02/04/mp4/190204084208765161.mp4" style="position:absolute;width:350px; height:500px;">
占位的标签
</mytag>
强制开启X5WebView同层渲染
X5同层渲染能力默认是关闭的,通过云端开关控制,通过分析发现,可以强制修改本地SP属性,强制打开
if (mWebView.getX5WebViewExtension()!=null){
//强制设置EMBEDDED云控开关enable
SharedPreferences tbs_public_settings = getSharedPreferences("tbs_public_settings", Context.MODE_PRIVATE);
SharedPreferences.Editor edit = tbs_public_settings.edit();
edit.putInt("MTT_CORE_EMBEDDED_WIDGET_ENABLE",1);
edit.apply();
}else {
Log.d(TAG, "init: 非x5内核");
}
向浏览器注册目标占位标签的原生控件
使用registerEmbeddedWidget
方法,可以想浏览器内核注册,需要原生来接管的占位的标签,第一个参数
是需要接管的标签名
,第二个参数
是工厂创建对应原生标签对象的工厂接口
//注册dom树中占位标签,创建对应的原生组件
boolean result = mWebView.getX5WebViewExtension().registerEmbeddedWidget(new String[]{"mytag"}, new IEmbeddedWidgetClientFactory() {
@Override
public IEmbeddedWidgetClient createWidgetClient(String s, Map<String, String> map, IEmbeddedWidget iEmbeddedWidget) {
Log.d(TAG, "init: createWidgetClient s"+s);
Log.d(TAG, "init: createWidgetClient map"+map.toString());
return new VideoEmbeddedWidgetClient(BrowserActivity.this);
}
});
其中createWidgetClient
方法参数意义
s
标签名,大写map
该标签的属性,在html中指定的iEmbeddedWidget
提供的原生的该标签的代理接口
下面是map打印的内容
init: createWidgetClient map{src=https://vfx.mtime.cn/Video/2019/02/04/mp4/190204084208765161.mp4, style=position:absolute;width:350px; height:500px;, id=mytag}
处理原生占位控件的实现IEmbeddedWidgetClient
原生如何接管替换占位标签,主要的实现类是IEmbeddedWidgetClient
public interface IEmbeddedWidgetClient {
void onSurfaceCreated(Surface var1);
void onSurfaceDestroyed(Surface var1);
boolean onTouchEvent(MotionEvent var1);
void onRectChanged(Rect var1);
void onVisibilityChanged(boolean var1);
void onDestroy();
void onActive();
void onDeactive();
void onRequestRedraw();
}
首先,IEmbeddedWidgetClient
并不是一个原生的View,而是给原生提供的该标签区域的绘制的入口,从onSurfaceCreated
和onSurfaceDestroyed
可以理解;
既然不是原生的View绘制,X5还是提供了类比View的属性,从API命名可以简单看出来其作用;
onSurfaceCreated
该标签可以绘制,请求原生API处理onSurfaceDestroyed
该标签视图销毁,请求原生销毁onTouchEvent
触摸事件分发onRectChanged
该标签在WebView中坐标变化回调(例如滚动,改变宽高)onVisibilityChanged
该标签显示隐藏onDestroy
该标签被移除,或者display = none
演示个Demo
熟悉了X5的API,写个简单的Demo玩一下
Demo的设计思路是在一个垂直滚动的网页中,嵌入一个原生的相机,原生的相机要正常的采集显示,且前端代码可以控制相机标签的显示隐藏,同步滚动等基本操作;
网页
<!DOCTYPE html>
<html>
<head>
<title>测试网页</title>
<meta charset="UTF-8">
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no" name="viewport">
<script type="text/javascript"> window.onload = touchtouch; function touchtouch(){ var camera = document.getElementById('camera'); console.log("camera:"+camera) camera.addEventListener("touchStart",handlerTouch,false); camera.addEventListener("touchend",handlerTouch,false); camera.addEventListener("touchcancel",handlerTouch,false); camera.addEventListener("touchleave",handlerTouch,false); camera.addEventListener("touchmove",handlerTouch,false); } function handlerTouch(evt){ log(evt); } </script>
</head>
<body>
<p>测试网页哈哈哈</p>
<div>
<div style="background-color: aqua; height: 100px;text-align: center;">1</div>
<div style="background-color: gray; height: 100px;text-align: center;">2</div>
<div style="background-color: rgb(80, 69, 69);height:500px;">
<camera cameraId=0 style="position:absolute;width:350px; height:500px;">
相机占位标签
</camera>
<a href="https://www.baidu.com" style="position:absolute;color:rgba(187, 255, 0, 0.482)"> 点击跳转哈哈哈</a>
</div>
<div style="background-color: gold; height: 100px;text-align: center;">4</div>
<div style="background-color: red; height: 100px;text-align: center;">5</div>
<div style="background-color: green; height: 100px;text-align: center;">6</div>
</div>
</body>
</html>
Java实现
public class CameraEmbeddedWidgetClient implements IEmbeddedWidgetClient {
private String TAG = "VideoEmbeddedWidgetClient";
private Rect rect;
private CameraHelper cameraHelper;
public CameraEmbeddedWidgetClient(Context c) {
cameraHelper = new CameraHelper(c);
}
@Override
public void onSurfaceCreated(Surface surface) {
Log.d(TAG, "onSurfaceCreated: ");
// Canvas canvas = surface.lockCanvas(rect);
// canvas.drawColor(Color.parseColor("#7f000000"));
// surface.unlockCanvasAndPost(canvas);
cameraHelper.preview(surface);
}
@Override
public void onSurfaceDestroyed(Surface surface) {
Log.d(TAG, "onSurfaceDestroyed: ");
cameraHelper.release();
}
}
前端样式改变和Native事件触发
指定样式display:none
原生回调onVisibilityChanged(false)
和onDestroy
指定样式display:block
重新创建新的Client指定样式visibility:visible
原生回调onVisibilityChanged(true)
指定样式visibility:hidden
原生回调onVisibilityChanged(false)
移除当前dom
等效于display:none
触摸事件的验证
必须得在js中设置改标签的事件监听
camera.addEventListener("touchStart",handlerTouch,false);
camera.addEventListener("touchend",handlerTouch,false);
camera.addEventListener("touchcancel",handlerTouch,false);
camera.addEventListener("touchleave",handlerTouch,false);
camera.addEventListener("touchmove",handlerTouch,false);
原生接受事件处理
IEmbeddedWidgetClient实现类
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
Log.d(TAG, "onTouchEvent: "+motionEvent.toString());
float x = motionEvent.getX();
float y = motionEvent.getY();
int action = motionEvent.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
initX = x;
initY = y;
intercepted = false;
return false;
case MotionEvent.ACTION_MOVE:
float dx = x - initX;
float dy = y - initY;
if (!intercepted && Math.abs(dy)>Math.abs(dx) && Math.abs(dy)>16){
intercepted = true;
}
break;
case MotionEvent.ACTION_UP:
break;
}
return intercepted;
}
总结
本文主要分享X5内核隐藏的同层渲染能力,用于学习交流,但是官方没有明确的文档说明,所以引入项目请谨慎;如果您对此该话题兴趣,不妨亲手折腾一下。
今天的文章【浏览器技术】解锁X5内核WebView同层渲染能力分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14361.html