wow_web_page.dart 10.6 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';

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;
  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<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("$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<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("$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");
              },
            ),
          )),
      // ),
    );
  }
}