79 lines
2.1 KiB
Dart
79 lines
2.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:webview_flutter/webview_flutter.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
class MyWebView extends StatefulWidget {
|
|
final String url;
|
|
final Function()? onLoad;
|
|
final Function(MyWebView view, String msg)? onMessage;
|
|
|
|
const MyWebView({
|
|
Key? key,
|
|
required this.url,
|
|
this.onLoad,
|
|
this.onMessage,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
State<MyWebView> createState() => _MyWebViewState();
|
|
}
|
|
|
|
class _MyWebViewState extends State<MyWebView> {
|
|
late final WebViewController _controller;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_controller = WebViewController()
|
|
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
|
..setNavigationDelegate(
|
|
NavigationDelegate(
|
|
onPageFinished: (url) {
|
|
widget.onLoad?.call();
|
|
},
|
|
onWebResourceError: (error) {
|
|
print("WebView 加载错误: ${error.description}");
|
|
},
|
|
onNavigationRequest: (NavigationRequest request) {
|
|
final url = request.url;
|
|
if (url.startsWith('http') || url.startsWith('https')) {
|
|
return NavigationDecision.navigate;
|
|
}
|
|
if (url.startsWith('weixin://')) {
|
|
_launchWeChatUrl(url);
|
|
return NavigationDecision.prevent;
|
|
}
|
|
print('拦截未知协议: $url');
|
|
return NavigationDecision.prevent;
|
|
},
|
|
),
|
|
)
|
|
..addJavaScriptChannel(
|
|
'FlutterChannel',
|
|
onMessageReceived: (msg) {
|
|
widget.onMessage?.call(widget, msg.message);
|
|
},
|
|
)
|
|
..loadRequest(Uri.parse(widget.url));
|
|
}
|
|
|
|
void _launchWeChatUrl(String url) async {
|
|
final uri = Uri.parse(url);
|
|
if (await canLaunchUrl(uri)) {
|
|
await launchUrl(uri);
|
|
} else {
|
|
print('⚠️ 无法跳转微信: $url');
|
|
}
|
|
}
|
|
|
|
// 提供方法给外部调用 JS
|
|
void sendData(String data) {
|
|
_controller.runJavaScript("window.postMessage('$data')");
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return WebViewWidget(controller: _controller);
|
|
}
|
|
} |