好了,接下来开始进入正题

本文着重介绍于 透明webview的弹窗效果与管理

让我们来看看Dialog和WebView同时应用于我们的弹窗管理方案会迸发出怎么样的花火吧!

Webview策略拓展

在项目开始之初就已经打算 将类不同但在意义上为弹窗的对应不同的策略进行扩展,

Webview的扩展形式为WebViewLayerStrategyImpl,

关于Webview的内容很多,多到足够写成一份单独的文章了 关于webview的配置,一些前任跨过的深坑,如何设计一个优雅健壮的androidWebview 这里可以推荐大家看

基于考拉电商平台的WebView实践

分析的很全面 在实现时考虑的方面很广 看完之后收益匪浅的一篇博文

再说框架本身, 内置对Webview的支持 并且对Webview进行了一系列配置 包括 Websetting Chromeclient Webclient 当然用户可以自定义这些配置已满足其独特的业务功能,这里推荐用户实现自定义配置时 继承内置的配置组件 已满足功能运转

当然,单单的webview支持是不足以满足我们繁杂的业务的

框架为您提供了多种Webview策略下的功能拓展:

1.统一Webview情形下的触摸监听

如下图 全屏透明webview总是存在web控件和原生控件的异同

框架 将其划分为内部区域与外部区域(实体与空心) 能统一大部分的弹窗触摸反馈, 用户可以实现此接口来自定义不同种类弹窗的触摸之后的效果


/**
• 弹窗的触摸机制 统一 分为实体区域 和 外围区域 触摸时的事件收发可以自定义
 */
 public interface LayerTouchSystem {
 //触摸到外部区域
 void onTouchOutSideArea(IPop iPop);
 //触摸到内部区域
 void onTouchSolidArea(IPop iPop);
 }

已经默认实现了Webview弹窗种类下的触摸效果

通常情况下全屏Webview会拦截触摸事件 对于弹窗来说他只需一小部分为其触摸区域 其他区域的点击需要下发事件到Native,下面是触摸事件的简单分析

这里关键点在于onTouchEvent的处理 Webview本身是拦截事件的 为此我们需要一个标识-什么时候需要拦截?

这里贴上框架是如何处理的

@Override
 public boolean onTouch(View v, MotionEvent event) {int alpha=0;
 //每一次触摸生成bitmap
 Bitmap bitmap= PopUtils.getBitmapFromView(this);
 //获取触摸点的ARGB的alpha值 将位图回收
 if (null != bitmap) {
 int pixel = bitmap.getPixel((int)event.getX(), (int)event.getY());
 alpha = Color.alpha(pixel);
 bitmap.recycle();
 }if(alpha==255){//实体
 layerTouchSystemImpl.onTouchSolidArea(this);
 }else {
 layerTouchSystemImpl.onTouchOutSideArea(this);
 }
 return false;
 }

首先设置onTouchListenr的监听

每一次触摸时我会生成当前点击像素的位图拿到当前点击的点的透明度

之后回收位图 根据透明度调用事先设置的回调即可

事件分发到onTouchEvent即可根据回调的状态 设置拦截还是分发事件给native

PS: 考虑到业务场景的不同 定制程度比较高的应用 建议实现属于自己的扩展

(这里存在的问题是动态特效弹窗详情下,触摸会出现卡顿,各位大佬如果有更好的方案,请在评论区留下您宝贵的建议)

2.默认内置JS原生交互方式

/**
• 混合开发管理 用户可自定义
 */
 public interface HybirdManager {
//注入JSBridge 时机在onreceivetitle
 void injectJsBridge(WebView webView,String jsName);//调用本地提供的基础服务 时机 1.jsprompt 2.post请求 3.原生 4.shouldOverrideUrlLoading
 void invokeAppServices(String instruction) ;//加入JS中android本地对象 时机webview初始化
 void addUpJavaNativeJSInterface(WebView webView, String windowObjName);}

对于Webview弹窗来说与JS的交互是不可缺少的,市面上有许多与JS交互的框架,Android同样有着原生支持,支持用户自定义与弹窗交互的方式,也同样提供了基于JSBridge和原生的默认交互实现,可根据业务与喜好择一使用

这里为了说明方便将下文的交互概念稍微统一

原生调H5为提供基础扩展,同理H5调原生为调用基础服务

中提供了默认的基础服务组件 PopWebViewService

主要包含弹窗 显示和消失等基本功能 和适合各个项目的统一路由服务

当网页显示的时候 我们可以在web调试器console中看到DOM对象的属性

PS: 这里的路由 JS传的是调用客户端服务的基础协议 这个协议由jsbridge内部形成 类似结构router://type=xxx?value=yyy,是由用户根据其业务决定的

内置JSbridge

框架中已经内置了Jsbridge,这里就不贴出代码一一说明了

简单的放一张原理图阐述双端的交互机制

注入时机

框架在这里采取在加载完头部标题时注入的机制

@Override
 public void onReceivedTitle(WebView view, String title) {
 //注入JSBridge的时机
 if(mHybirdImpl!=null){
 mHybirdImpl.injectJsBridge(view,jsBridgeName);
 }
 super.onReceivedTitle(view, title);
 }

根据考拉团队的做法

通过设置加载阈值 在监听WebViewClient.onProgressChanged()函数时根据进度来注入也是可行的

回调服务时机

考虑到现今WebView的回调特点, 尽可能全面的在四种方案回调了基础服务接口 并在下面分析了各自的优缺点,用户可择其使用

1.JsPrompt

侵入WebChromeClient.onJsPrompt(webview, url, message, defaultValue, result)实现通信。

优点 返回值类型多样 消息长度上限高

缺点 可能需要处理弹窗问题

2.拦截JS Post请求

优点 通过请求来做操作 可以进行鉴权加密 提高安全性

缺点 请求体body里的内容android端无法接收到(IOS是可以拿到的)

3.Native函数也接收回调