import 'dart:convert'; import 'package:cs_resources/theme/app_colors_theme.dart'; import 'package:flutter/material.dart'; import 'package:plugin_platform/engine/image/image_nine_grid.dart'; import 'package:shared/utils/log_utils.dart'; import 'package:url_launcher/url_launcher.dart'; import 'dart:io'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:widgets/ext/ex_widget.dart'; import 'package:widgets/my_appbar.dart'; import 'package:cs_resources/constants/color_constants.dart'; import 'package:widgets/my_button.dart'; /// webview 封装 // ignore: must_be_immutable class WebViewPage extends StatefulWidget { final String? initialUrl; bool? showAppbar = true; Map? arguments = {'title': '', 'initialUrl': ''}; String? bottomBtnTxt; //是否有底部按钮,底部按钮的文本 VoidCallback? bottomBtnAction; //底部按钮的回调 List? actions = []; WebViewPage({Key? key, this.showAppbar, this.initialUrl, this.arguments, this.actions, this.bottomBtnTxt, this.bottomBtnAction}) : super(key: key); @override _WebViewPageState createState() => _WebViewPageState(); } class _WebViewPageState extends State { WebViewController? webViewController; final _key = UniqueKey(); String? title; bool _showAppbar = true; int _stackToView = 1; String? _initialUrl; double _webViewHeight = 200; @override void initState() { super.initState(); title = widget.arguments != null ? widget.arguments!['title'] : null; _showAppbar = widget.showAppbar ?? true; Log.d("传入的initialUrl:${widget.initialUrl}"); _initialUrl = widget.initialUrl ?? widget.arguments!['initialUrl']; _initializeController(); } void _initializeController() { webViewController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setBackgroundColor(const Color(0x00000000)) ..setNavigationDelegate( NavigationDelegate( onProgress: (int progress) { if (progress == 100) { Future.delayed(const Duration(milliseconds: 500)).then((value) => { // 获取页面高度 _getWebViewHeight() }); } }, onPageStarted: (String url) { if (mounted) { setState(() { _stackToView = 1; }); } }, onPageFinished: (String url) { if (mounted) { setState(() { _stackToView = 0; }); } }, onWebResourceError: (WebResourceError error) {}, onNavigationRequest: (NavigationRequest request) async { if (request.url.startsWith('tel:')) { // 拦截tel链接 if (!await launchUrl(Uri.parse(request.url))) throw 'Unable to activate the call function'; return NavigationDecision.prevent; // 阻止WebView导航到该链接 } return NavigationDecision.navigate; }, ), ) ..loadRequest(Uri.parse(_initialUrl ?? "")); } _getWebViewHeight() async { // try { // final result = await webViewController?.runJavaScriptReturningResult(''' // new Promise((resolve) => { // const scrollHeight = document.documentElement.scrollHeight; // resolve(scrollHeight); // }); // '''); // return double.parse(result.toString()); // } catch (e) { // return 300.0; // 默认高度 // } // 方式二: var originalHeight = await webViewController?.runJavaScriptReturningResult("document.body.offsetHeight;"); _webViewHeight = double.parse(originalHeight.toString()); if (mounted) { setState(() { _webViewHeight = _webViewHeight <= 0 ? 300 : _webViewHeight; }); } } @override void dispose() async { super.dispose(); // 销毁 WebView 实例 webViewController?.loadHtmlString('about:blank'); webViewController?.clearCache(); } @override void didUpdateWidget(covariant WebViewPage oldWidget) { super.didUpdateWidget(oldWidget); if (widget.initialUrl != oldWidget.initialUrl) { super.didUpdateWidget(oldWidget); } } // 返回与后退的处理 Future _onWillPop() async { if (webViewController == null) { Log.d("WebView都没有加载成功,直接返回退出即可"); //WebView都没有加载成功,可以直接退出 Navigator.of(context).pop(); return false; } else { //如果点击了内部链接之后,可以返回,则直接返回 if (await webViewController!.canGoBack()) { Log.d("点击内部链接,可以后台,调用后退"); await webViewController!.goBack(); return false; // 防止退出页面 } else { Log.d("点击内部链接,无法后退,直接返回"); Navigator.of(context).pop(); // 不能后退则退出当前页面 return true; } } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: context.appColors.whiteBG, appBar: _showAppbar ? MyAppBar.appBar( context, title ?? "", backgroundColor: context.appColors.backgroundWhite, actions: widget.actions, backCallback: _onWillPop, ) : null, body: SafeArea( bottom: true, top: false, child: Column( children: [ IndexedStack( index: _stackToView, children: [ //WebView控件 Column( children: [ Expanded( child: WillPopScope( onWillPop: _onWillPop, child: WebViewWidget( key: _key, controller: webViewController!, ), ), ) ], ), //Loading加载控件 Container( color: Colors.white, child: const Center( child: CircularProgressIndicator( strokeWidth: 3, valueColor: AlwaysStoppedAnimation(ColorConstants.appBlue), ), ), ), ], ).expanded(), //底部按钮 if (widget.bottomBtnTxt != null) MyButton( onPressed: widget.bottomBtnAction, text: widget.bottomBtnTxt ?? "", textColor: Colors.white, backgroundColor: context.appColors.btnBgDefault, fontWeight: FontWeight.w500, type: ClickType.throttle, fontSize: 16, minHeight: 50, radius: 0, ) ], ), )); } }