1、需求背景
实现一个不全屏的,支持加载本地html资源的webview
2、结论先行
选用了官方的webview_flutter。总结了下实践的过程,分析几个插件有如下特点:
flutter_inappwebview:
问题:
1.键盘有时候收不起来.
2.文本框不响应文字输入
3.部分Android机型上,js->flutter 不通.分析查看是native层的js接口没有被回调,原生的js接口.(setJavaScriptEnable为true),高频概率性出现,危害程度可以说是致命性。
优势:
1、能加载本地h5资源
2、支持不用全屏。
除了以上问题,特别是js的调用问题 。否则这个框架是非常适合目前的场景了。
flutter_webview_plugin
1.只能全屏
2.不能加载本地H5
3.无键盘问题
需求界面是flutter ui+webview混合组成。同时加载本地h5要解析成字符串后展示,感觉有点麻烦,挺不靠谱的感觉。诸多问题,放弃。
webview_flutter:
1.解决了键盘问题(目前只是实验性,还是有出问题的概率,但还是能用)
2.IOS端不支持加载本地html。
3、官方插件。
3、优化过程
综合上踩坑总结,最后选用了webview_flutter。接下来就是解决不支持加载本地html的问题。
在Android端,加载本地本地html,只需要使用:
"file:///android_asset/flutter_assets/assets/index.html
的方式即可加载本地html。
加压过apk就你能看到,flutter的资源会被打包进文件夹flutter_assets下。可以加压apk查看。按照Android WebView loadUrl加载本地html的方式拼上以上路径即可找到本地html。
而在IOS端,加载html的实现方式为:https://github.com/flutter/plugins/blob/master/packages/webview_flutter/ios/Classes/FlutterWebView.m
- (bool)loadUrl:(NSString*)url withHeaders:(NSDictionary
*)headers { NSURL* nsUrl = [NSURL URLWithString:url];
if (!nsUrl) {
return false;
}
//创建请求
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:nsUrl];
[request setAllHTTPHeaderFields:headers];
//发起请求
[_webView loadRequest:request];
return true;
}
而ios加载本地html方式这样是行不通的。需要先找到本地资源,然后调用loadFileURL:url的方式。为了兼容而改成以下方式实现:
- (bool)loadUrl:(NSString*)url withHeaders:(NSDictionary*)headers {
NSURL* nsUrl = [NSURL URLWithString:url];
NSLog(@"webview_flutter: %@", nsUrl);
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:nsUrl];
[request setAllHTTPHeaderFields:headers];
//判断是url使用不用的加载方式
if([url hasPrefix:@"http"]) {
[_webView loadRequest:request];
}else{
//为减少对三方插件的修改,加载本地html,文件名暂时只支持命名为名index
if (@available(iOS 9.0, *)) {
NSURL *findUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/Frameworks/App.framework/flutter_assets/webres/%@", [[NSBundle mainBundle] bundlePath], @"index.html"]];
NSLog(@"Debug >>>> %@", findUrl);
NSString *loadUrl = [findUrl.absoluteString stringByReplacingOccurrencesOfString:@"index.html" withString:url];
NSURL * url = [NSURL URLWithString:loadUrl];
NSLog(@"Debug >>>> load url %@", url);
[_webView loadFileURL:url allowingReadAccessToURL:[url URLByDeletingLastPathComponent]];
} else {
// Fallback on earlier versions
NSLog(@"webview_flutter: loadFileUrl error");
}
}
return true;
}
成功。因本人是Android出身,以上代码花了大半个小时才写出来,还是object-c。
总算搞出来了。
4、总结
webview_flutter不管在Android还是iOS,实现的方式首先于flutter的platforview的局限性,导致了键盘的问题https://github.com/flutter/plugins/tree/master/packages/webview_flutter。目前还没有一个完美的解决方案,不过勉强能用,能接受。从本质上最看好flutter_webview_plugin的实现方式,用了纯flutter的方式来实现,但只能全屏。有空的话可以多研究下。而inappwebview的方式和官网本质上是一样的,都是采用了原生的方式,但键盘问题inappwebview表现要好很多。综上评估各方面评估还是选了官方的插件加以完善来适应当前的项目。
从去年下半年开始接触Flutter预研了一个多月,后面中断了,现在因产品需要重新操练了起来,Flutter越玩越发现好玩,菜鸟慢慢起飞吧,加油!