IOS模拟器无法加载网页,插件版本flutter_webview_plugin: ^0.4.0

来源:12-10 基于自定义WebView实现H5混合开发-3【H5混合实战】

weixin_慕无忌8341780

2021-07-24

IOS info.plist文件也按照官方说明配置了,但是我运行了课程代码,发现是可以,也没有报空安全错误,对比了下代码,只是增加了StreamSubscription变量的初始化,加了问号,断点调试,发现widget.url是有值,就算我替换成百度的链接,也是打不开,在pub上的issues查了也没相关问题,纠结啊

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSAllowsArbitraryLoadsInWebContent</key>
        <true/>
    </dict>
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

const CATCH_URLS = ['m.ctrip.com/', 'm.ctrip.com/html5/', 'm.ctrip.com/html5'];

class WebView extends StatefulWidget {
  String url;
  final String statusBarColor;
  final String title;
  final bool hideAppBar;
  final bool backForbid;

  WebView(
      {required this.url,
      required this.statusBarColor,
      required this.title,
      required this.hideAppBar,
      this.backForbid = false}) {
    if (url != null && url.contains('ctrip.com')) {
      //fix 携程H5 http://无法打开问题
      url = url.replaceAll("http://", 'https://');
    }
  }

  @override
  _WebViewState createState() => _WebViewState();
}

class _WebViewState extends State<WebView> {
  final webviewReference = FlutterWebviewPlugin();
  StreamSubscription<String>? _onUrlChanged;
  StreamSubscription<WebViewStateChanged>? _onStateChanged;
  StreamSubscription<WebViewHttpError>? _onHttpError;

  bool exiting = false; //是否返回的标志位
  _isToMain(String url) {
    bool contain = false;
    for (final value in CATCH_URLS) {
      if (url.endsWith(value)) {
        contain = true;
        break;
      }
    }
    return contain;
  }

  @override
  void initState() {
    super.initState();
    webviewReference.close();
    _onUrlChanged = webviewReference.onUrlChanged.listen((event) {});
    _onStateChanged =
        webviewReference.onStateChanged.listen((WebViewStateChanged state) {
      switch (state.type) {
        case WebViewState.startLoad:

          ///防止返回首页
          if (_isToMain(widget.url) && !exiting) {
            if (widget.backForbid) {
              webviewReference.launch(widget.url);
            } else {
              Navigator.pop(context);
              exiting = true;
            }
          }
          break;
        default:
          break;
      }
    });
    _onHttpError =
        webviewReference.onHttpError.listen((WebViewHttpError error) {
      print(error);
    });
  }

  @override
  void dispose() {
    super.dispose();
    _onUrlChanged?.cancel();
    webviewReference.dispose();
    _onStateChanged?.cancel();
    _onHttpError?.cancel();
  }

  @override
  Widget build(BuildContext context) {
    String statusBarColorStr =
        widget.statusBarColor.isEmpty ? 'ffffff' : widget.statusBarColor;
    Color backButtonColor;
    if (statusBarColorStr == 'ffffff') {
      backButtonColor = Colors.black;
    } else {
      backButtonColor = Colors.white;
    }
    return Scaffold(
      body: Column(
        children: [
          _appBar(
              Color(int.parse('0xff' + statusBarColorStr)), backButtonColor),

          ///使用expanded撑满屏幕
          Expanded(
            child: WebviewScaffold(
              url: widget.url,
              userAgent: 'null', //防止携程H5页面重定向到打开携程APP ctrip://wireless/xxx的网址
              ///缩放
              withZoom: true,

              ///页面缓存
              withLocalStorage: true,

              hidden: true,
              initialChild: Container(
                color: Colors.white,
                child: Center(
                  child: Text('Waiting....'),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }

  _appBar(Color backGroundColor, Color backButtonColor) {
    if (widget.hideAppBar) {
      return Container(
        height: 30,
        color: backGroundColor,
      );
    }
    return Container(
      color: backGroundColor,
      padding: EdgeInsets.fromLTRB(0, 40, 0, 10),
      child: FractionallySizedBox(
        widthFactor: 1,
        child: Stack(
          children: [
            ///返回按钮
            GestureDetector(
              onTap: () {
                Navigator.pop(context);
              },
              child: Container(
                margin: EdgeInsets.only(left: 10),
                child: Icon(
                  Icons.close,
                  color: backButtonColor,
                  size: 26,
                ),
              ),
            ),

            ///标题
            Positioned(
                left: 0,
                right: 0,
                child: Center(
                  child: Text(
                    widget.title,
                    style: TextStyle(fontSize: 20, color: backButtonColor),
                  ),
                ))
          ],
        ),
      ),
    );
  }
}

写回答

1回答

CrazyCodeBoy

2021-07-26

换成:

webview_flutter: ^2.0.8

插件看看还是否有这个问题,代码可参考下:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

const CATCH_URLS = ['m.ctrip.com/', 'm.ctrip.com/html5/', 'm.ctrip.com/html5'];

class HiWebView extends StatefulWidget {
  String? url;
  final String? statusBarColor;
  final String? title;
  final bool? hideAppBar;
  final bool backForbid;

  HiWebView(
      {this.url,
      this.statusBarColor,
      this.title,
      this.hideAppBar,
      this.backForbid = false}) {
    if (url != null && url!.contains('ctrip.com')) {
      //fix 携程H5 http://无法打开问题
      url = url!.replaceAll("http://", 'https://');
    }
  }

  @override
  _HiWebViewState createState() => _HiWebViewState();
}

class _HiWebViewState extends State<HiWebView> {
  bool exiting = false;

  @override
  void initState() {
    super.initState();
  }

  _isToMain(String? url) {
    bool contain = false;
    for (final value in CATCH_URLS) {
      if (url?.endsWith(value) ?? false) {
        contain = true;
        break;
      }
    }
    return contain;
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    String statusBarColorStr = widget.statusBarColor ?? 'ffffff';
    Color backButtonColor;
    if (statusBarColorStr == 'ffffff') {
      backButtonColor = Colors.black;
    } else {
      backButtonColor = Colors.white;
    }
    return Scaffold(
      body: Column(
        children: <Widget>[
          _appBar(
              Color(int.parse('0xff' + statusBarColorStr)), backButtonColor),
          Expanded(
              child: WebView(
                  //防止携程H5页面重定向到打开携程APP ctrip://wireless/xxx的网址
                  initialUrl: widget.url,
                  javascriptMode: JavascriptMode.unrestricted,
                  navigationDelegate: (NavigationRequest request) {
                    if (_isToMain(request.url)) {
                      print('blocking navigation to $request}');
                      Navigator.pop(context);
                      return NavigationDecision.prevent;
                    }
                    print('allowing navigation to $request');
                    return NavigationDecision.navigate;
                  }))
        ],
      ),
    );
  }

  _appBar(Color backgroundColor, Color backButtonColor) {
    if (widget.hideAppBar ?? false) {
      return Container(
        color: backgroundColor,
        height: 30,
      );
    }
    return Container(
      color: backgroundColor,
      padding: EdgeInsets.fromLTRB(0, 40, 0, 10),
      child: FractionallySizedBox(
        widthFactor: 1,
        child: Stack(
          children: <Widget>[
            GestureDetector(
              onTap: () {
                Navigator.pop(context);
              },
              child: Container(
                margin: EdgeInsets.only(left: 10),
                child: Icon(
                  Icons.close,
                  color: backButtonColor,
                  size: 26,
                ),
              ),
            ),
            Positioned(
              left: 0,
              right: 0,
              child: Center(
                child: Text(
                  widget.title ?? '',
                  style: TextStyle(color: backButtonColor, fontSize: 20),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}


1
0

Flutter从入门到进阶 实战携程网App 一网打尽核心技术

解锁Flutter开发新姿势,,系统掌握Flutter开发核心技术。

4788 学习 · 3274 问题

查看课程