wow_web_page.dart 10.9 KB
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';
import '../../utils/toast_util.dart';

class WowWebViewPage extends StatefulWidget {
  WowWebViewPage(
      {super.key, required this.urlStr, required this.webViewTitle});

  final String urlStr;
  String webViewTitle;

  @override
  State<StatefulWidget> 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<Color>(Colors.blue),
  );
}

class _WowWebViewPageState extends State<WowWebViewPage> {
  late InAppWebViewController? _inAppWebViewController;
  final GlobalKey webViewKey = GlobalKey();
  double _progress = 0;
  bool isCanGoBack = false;
  bool isCanForward = false;
  late final String defaultWebViewTitle = widget.webViewTitle;

  // 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<String?> getUrl() {
    if (_inAppWebViewController == null) {
      return Future.sync(() => null);
    }
    return _inAppWebViewController!.getUrl().then((uri) => uri.toString());
  }

  Future<void> 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("WQF onPageStarted $url");
    //         EasyLoading.show();
    //       },
    //       onPageFinished: (String url) {
    //         Log.d("WQF onPageFinished $url");
    //         EasyLoading.dismiss();
    //       },
    //       onWebResourceError: (WebResourceError error) {
    //         Log.d("WQF onWebResourceError ${error.description}");
    //         EasyLoading.showError(error.description);
    //       },
    //       onUrlChange: (UrlChange change) {
    //         Log.d("WQF onUrlChange ${change.url}");
    //       },
    //       onNavigationRequest: (NavigationRequest request) async {
    //         var url = request.url;
    //         Log.d("WQF onNavigationRequest $url");
    //
    //         /// Allow the navigation
    //         // return NavigationDecision.navigate;
    //         /// Block the navigation
    //         /// return NavigationDecision.prevent;
    //         if (url.startsWith("alipay:") || url.startsWith("alipays")) {
    //           Log.d("WQF 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<bool> 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: <Widget>[
              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<UserScript>([]),
                initialOptions: webViewSettings,
                onWebViewCreated: (controller) {
                  _inAppWebViewController = controller;
                },
                onTitleChanged:
                    (InAppWebViewController controller, String? title) {
                      Log.d(
                          "WQF 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(
                      "WQF shouldOverrideUrlLoading url=$url scheme=${url?.scheme}");
                  if (![
                    "http",
                    "https",
                    "file",
                    "chrome",
                    "data",
                    "javascript",
                    "about",
                  ].contains(url?.scheme ?? "")) {
                    Log.d(
                        "WQF shouldOverrideUrlLoading contains scheme=${url?.scheme} uri=${url?.data?.uri} url=$url");
                    Log.d("WQF canLaunchUrl(url)=${canLaunchUrl(url!)}");
                    await canLaunchUrl(url)
                        ? await launchUrl(url)
                        : showToast("对不起,打不开链接地址:$url");
                    return NavigationActionPolicy.CANCEL;
                  }
                  return NavigationActionPolicy.ALLOW;
                },
                onLoadStop: (controller, url) async {
                  Log.d("WQF 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(
                      "WQF onReceivedError request=$request error=$code message=$message");
                },
                onLoadHttpError: (controller, request, errorResponse, message) {
                  Log.d(
                      "WQF onReceivedError request=$request errorResponse=$errorResponse message=$message");
                },
                onProgressChanged: (controller, progress) {
                  Log.d("WQF onProgressChanged progress=$progress");
                  //进度从0 ~ 100
                  setState(() {
                    _progress = progress / 100.0;
                  });
                },
                onUpdateVisitedHistory: (controller, url, androidIsReload) {
                  Log.d("WQF onUpdateVisitedHistory url=$url");
                },
                // onLoadResourceWithCustomScheme: (controller, request) {
                //   Log.d("WQF onLoadResourceWithCustomScheme request=$request");
                // },
                onConsoleMessage: (controller, consoleMessage) {
                  // Log.d("WQF onConsoleMessage consoleMessage=$consoleMessage");
                },
              ),
            )),
      // ),
    );
  }
}