import 'dart:collection'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/common/widgets/we_app_bar.dart'; import '../../utils/log_util.dart'; class WowWebViewPage extends StatefulWidget { WowWebViewPage({super.key, required this.urlStr, required this.webViewTitle}); final String urlStr; String webViewTitle; @override State createState() { return _WowWebViewPageState(); } } /// 生成进度条组件,进度从0 ~ 1 _createProgressBar(double progress, BuildContext context) { return LinearProgressIndicator( backgroundColor: Colors.white70.withOpacity(0), value: progress == 1.0 ? 0 : progress, valueColor: const AlwaysStoppedAnimation(Colors.blue), ); } class _WowWebViewPageState extends State { late InAppWebViewController? _inAppWebViewController; final GlobalKey webViewKey = GlobalKey(); double _progress = 0; bool isCanGoBack = false; bool isCanForward = false; late final String defaultWebViewTitle = widget.webViewTitle; final String TAG = "WowWebViewPage"; // InAppWebViewSettings webViewSettings = InAppWebViewSettings( // useShouldOverrideUrlLoading: true, // mediaPlaybackRequiresUserGesture: true, // // /// android 支持HybridComposition // useHybridComposition: true, // allowsInlineMediaPlayback: true, // ); InAppWebViewGroupOptions webViewSettings = InAppWebViewGroupOptions( crossPlatform: InAppWebViewOptions( useShouldOverrideUrlLoading: true, // 是否需要跳转 mediaPlaybackRequiresUserGesture: false, // 设置为true,防止H5的音频自动播放 transparentBackground: true, ), android: AndroidInAppWebViewOptions( useHybridComposition: true, mixedContentMode: AndroidMixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW), ios: IOSInAppWebViewOptions( allowsInlineMediaPlayback: true, ), ); Future getUrl() { if (_inAppWebViewController == null) { return Future.sync(() => null); } return _inAppWebViewController!.getUrl().then((uri) => uri.toString()); } Future loadUrl(String url) { if (_inAppWebViewController == null) { return Future.sync(() => null); } return _inAppWebViewController! .loadUrl(urlRequest: URLRequest(url: Uri.parse(url))); } @override void initState() { super.initState(); /*if (Platform.isIOS) { LimitingDirectionCsx.setScreenDirection(DeviceDirectionMask.PortraitUpsideDown); } else { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); }*/ // _controller = WebViewController() // ..setJavaScriptMode(JavaScriptMode.unrestricted) // ..setBackgroundColor(const Color(0x00000000)) // ..setNavigationDelegate( // NavigationDelegate( // onProgress: (int progress) { // // Update loading bar. // }, // onPageStarted: (String url) { // Log.d("$TAG onPageStarted $url"); // EasyLoading.show(); // }, // onPageFinished: (String url) { // Log.d("$TAG onPageFinished $url"); // EasyLoading.dismiss(); // }, // onWebResourceError: (WebResourceError error) { // Log.d("$TAG onWebResourceError ${error.description}"); // EasyLoading.showError(error.description); // }, // onUrlChange: (UrlChange change) { // Log.d("$TAG onUrlChange ${change.url}"); // }, // onNavigationRequest: (NavigationRequest request) async { // var url = request.url; // Log.d("$TAG onNavigationRequest $url"); // // /// Allow the navigation // // return NavigationDecision.navigate; // /// Block the navigation // /// return NavigationDecision.prevent; // if (url.startsWith("alipay:") || url.startsWith("alipays")) { // Log.d("$TAG onNavigationRequest 支付宝 $url"); // launch(request.url); // return NavigationDecision.navigate; // } // if (url.startsWith('http:') || url.startsWith('https:')) { // return NavigationDecision.navigate; // } else { // try { // await launch(url); // } catch (e) { // print('Could not launch $request.url: $e'); // } // return NavigationDecision.prevent; // } // }, // ), // ) // ..loadRequest(Uri.parse(widget.urlStr)); } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () { Future canGoBack = _inAppWebViewController!.canGoBack(); return canGoBack.then((isCanGoBack) { if (isCanGoBack) { _inAppWebViewController!.goBack(); return false; } else { return true; } }); }, // return PopScope( // canPop: () async { // if (_controller != null) { // bool canGoBack = await _controller!.canGoBack(); // return !canGoBack; // } // return true; // }, // onPopInvoked: (PopDisposition disposition) async { // if (_controller != null) { // bool canGoBack = await _controller!.canGoBack(); // if (canGoBack) { // _controller!.goBack(); // return PopDisposition.popCancelled; // } // } // return PopDisposition.pop; // }, child: Scaffold( backgroundColor: Colors.red, appBar: WEAppBar( titleText: widget.webViewTitle, leadingWidth: 96, leading: Row( children: [ IconButton( icon: Image.asset( 'back_around'.assetPng, height: 40.h, width: 40.w, ), onPressed: () { if (isCanGoBack) { _inAppWebViewController!.goBack(); } else { Navigator.pop(context); } }, ), Visibility( visible: isCanGoBack, child: IconButton( // icon: Image.asset( // 'back_around'.assetPng, // height: 40.h, // width: 40.w, // ), icon: Icon(Icons.close), onPressed: () { Navigator.pop(context); }, ), ), ], ), ), body: Container( color: Colors.white, // child: SafeArea( child: InAppWebView( key: webViewKey, initialUrlRequest: URLRequest( url: Uri.parse(widget.urlStr), ), initialUserScripts: UnmodifiableListView([]), initialOptions: webViewSettings, onWebViewCreated: (controller) { _inAppWebViewController = controller; }, onTitleChanged: (InAppWebViewController controller, String? title) { Log.d("$TAG onTitleChanged title=$title`"); setState(() { if (title?.endsWith(".com") == true) { widget.webViewTitle = defaultWebViewTitle; } else { widget.webViewTitle = title ?? defaultWebViewTitle; } }); }, shouldOverrideUrlLoading: (controller, navigationAction) async { var url = navigationAction.request.url; Log.d( "$TAG shouldOverrideUrlLoading url=$url scheme=${url?.scheme}"); if (![ "http", "https", "file", "chrome", "data", "javascript", "about", ].contains(url?.scheme ?? "")) { Log.d("$TAG canLaunchUrl(url)=${canLaunchUrl(url!)}"); await canLaunchUrl(url) ? await launchUrl(url) : Log.e("对不起,打不开链接地址:$url"); return NavigationActionPolicy.CANCEL; } return NavigationActionPolicy.ALLOW; }, onLoadStop: (controller, url) async { Log.d("$TAG onLoadStop url=$url"); //页面加载完毕,显示隐藏AppBar的返回键 _inAppWebViewController!.canGoBack().then((canGoBack) => { setState(() { isCanGoBack = canGoBack; }) }); _inAppWebViewController!.canGoForward().then((canForward) => { setState(() { isCanForward = canForward; }) }); }, onLoadError: (controller, request, code, message) { Log.d( "$TAG onReceivedError request=$request error=$code message=$message"); }, onLoadHttpError: (controller, request, errorResponse, message) { Log.d( "$TAG onReceivedError request=$request errorResponse=$errorResponse message=$message"); }, onProgressChanged: (controller, progress) { Log.d("$TAG onProgressChanged progress=$progress"); //进度从0 ~ 100 setState(() { _progress = progress / 100.0; }); }, onUpdateVisitedHistory: (controller, url, androidIsReload) { Log.d("$TAG onUpdateVisitedHistory url=$url"); }, // onLoadResourceWithCustomScheme: (controller, request) { // Log.d("$TAG onLoadResourceWithCustomScheme request=$request"); // }, onConsoleMessage: (controller, consoleMessage) { // Log.d("$TAG onConsoleMessage consoleMessage=$consoleMessage"); }, ), )), // ), ); } }