flutter dependencies
dependencies:
flutter:
sdk: flutter
webview_flutter: ^0.3.15+1
fluttertoast: ^3.1.3
class _ComponentWebviewState extends State<ComponentWebview> {
bool _loading = false;
WebViewController _webViewController;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
//加载 远程网页 OR 本地网页
var isRemote = widget.url.contains('http');
return Stack(
children: <Widget>[
Scaffold(
body: isRemote ? loadRemoteUrl() : loadAssetsUrl(),
floatingActionButton: FloatingActionButton(
onPressed: () {
_webViewController
?.evaluateJavascript(
'customeFunc("Flutter 调用 JS Time: ${DateTime.now().toUtc()}")')
?.then((result) {
// You can handle JS result here.
print("customeFunc" + result);
});
},
child: Text('调用JS'),
),
),
//加载网页提示
uiLoading()
],
);
}
Widget uiLoading() {
if (_loading)
return Center(child:CircularProgressIndicator()) ;//Center(child: Icon(Icons.play_circle_filled));
else
return Container(height: 0.0, width: 0.0);
}
// 定义 网页中能够调用的 Flutter 方法
JavascriptChannel jsChannelShowToast(BuildContext context) {
return JavascriptChannel(
name: 'flutterShowToast',
onMessageReceived: (JavascriptMessage message) {
Fluttertoast.showToast(
msg: message.message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
});
}
///JS和Flutter通信的Channel;
/// js 调用 flutter 方法
List<JavascriptChannel> _getWebViewJavascriptChannels() {
return <JavascriptChannel>[
jsChannelShowToast(context),
];
}
_navigationDelegateHandle(NavigationRequest request) {
print('request.url =======> : ${request.url}');
//路由委托(可以通过在此处拦截url实现JS调用Flutter部分);
///通过拦截url来实现js与flutter交互
if (request.url.toLowerCase().startsWith('webviewflutterurl://')) {
// Fluttertoast.showToast(msg:'JS调用了Flutter By navigationDelegate');
print('blocking navigation to $request}');
return NavigationDecision.prevent;
///阻止路由替换,不能跳转,因为这是js交互给我们发送的消息
}
return NavigationDecision.navigate;
//允许路由替换
}
///页面加载完成处理
_onPageFinished(String url) async {
// 获取当前加载页面的 title
String title = await _webViewController.getTitle();
widget.titleChandge(title);
setState(() {
_loading = false;
});
print('Page finished url ====> : $url');
//添加一些 webview 初始化数据
var jsonData = {'platform': Platform.isAndroid ? 'android' : 'ios'};
var jsonDataString = jsonEncode(jsonData);
print(jsonDataString);
//通知网页服务器加载完成并触发加载完成事件
_webViewController
?.evaluateJavascript(
'triggerEventWebViewFlutterJSBridgeReady($jsonDataString)')
?.then((result) {
print(result);
});
}
}
Remote 网页
///加载 远程 html
Widget loadRemoteUrl() {
return WebView(
initialUrl: widget.url,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
setState(() { _loading = true; });
_webViewController = webViewController;
},
javascriptChannels: _getWebViewJavascriptChannels().toSet(),
navigationDelegate: (request) => _navigationDelegateHandle(request),
onPageFinished: (url) => _onPageFinished(url));
}
localhost 网页
需要引入
import 'dart:io';
import 'package:flutter/services.dart';
///加载 本地 html
Widget loadAssetsUrl() {
return FutureBuilder(
future: _loadHtmlFile(),
builder: (context, snapshot) => WebView(
initialUrl: Uri.dataFromString(snapshot.data, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')) .toString(),
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
setState(() { _loading = true; });
_webViewController = webViewController;
},
javascriptChannels: _getWebViewJavascriptChannels().toSet(),
navigationDelegate: (request) => _navigationDelegateHandle(request),
onPageFinished: (url) => _onPageFinished(url)));
}
/// 加载本地 HTML 文件
Future<String> _loadHtmlFile() async {
return await rootBundle.loadString(widget.url);
}
网页部分
<section style="text-align: center;">
<div id="content"> </div>
<button id="btnFlutterFunc">jquery调用Flutter</button> <hr>
<button onclick="showToast()">原生Js调用Flutter</button> <hr>
<a href="webviewflutterurl://fff?p1=123&p2=321">连接拦截 GO ==> :webviewflutterurl://fff?p1=123&p2=321</a>
</section>
<script type="text/javascript" src="./jquery.min.js"></script>
<script type="text/javascript">
function showToast(message) {
flutterShowToast.postMessage(message || "JS调用了Flutter");
}
// 首先需要提前定义好事件,并且注册相关的EventListener
var eventWebViewFlutterJSBridgeReady = new CustomEvent('webViewFlutterJSBridgeReady', {
detail: {
//平台 android OR ios
platform: ''
},
});
function triggerEventWebViewFlutterJSBridgeReady(jsonData) {
console.log(JSON.stringify(jsonData))
setTimeout(function () {
eventWebViewFlutterJSBridgeReady.detail.platform = jsonData.platform
if (window.dispatchEvent)
window.dispatchEvent(eventWebViewFlutterJSBridgeReady);
else
window.fireEvent(eventWebViewFlutterJSBridgeReady);
}, 200)
return '已触发事件:webViewFlutterJSBridgeReady:platform:${jsonData.platform}';
}
window.addEventListener('webViewFlutterJSBridgeReady', function (event) {
console.log('触发:webViewFlutterJSBridgeReady');
});
window.addEventListener('webViewFlutterJSBridgeReady', function (event) {
showToast('Js:CustomEvent:webViewFlutterJSBridgeReady'+JSON.stringify(event.detail));
});
function customeFunc(message) {
document.getElementById("content").innerHTML = message;
return 'customeFunc 调用完成'
}
$(function () {
var elementContent = $('.content');
var elementBtnFlutterFunc = $('#btnFlutterFunc');
elementBtnFlutterFunc.unbind('click').bind('click', function () {
showToast();
})
})
</script>
网页中加入 自定义事件 CustomEvent webViewFlutterJSBridgeReady
以便通知网页网页加载完成 在调用的时候初始化部分 信息 如 硬件平台信息 等
加载本地网页加载JQuery 还没研究透 ... 没找到方法
String title = 'webview title';
@override
Widget build(BuildContext context) {
var url = 'https://www.baidu.com';
url = 'http://www.baidu.com';
url = 'http://192.168.2.65:9777/Content/static/webview_flutter.html';
var now =new DateTime.now();
url = '$url?t=${now.toUtc()}';
// url = "assets/www/webview_flutter.html";
return Scaffold(
appBar: AppBar(title:Text(title)),
body: ComponentWebview(url: url,titleChandge: (value){
print(value);
setState(() {
title = value;
});
}),
);
}
网友评论