webview_flutter的使用

1.webview_flutter

官方链接见https://pub-web.flutter-io.cn/packages/webview_flutter

On iOS the WebView widget is backed by a WKWebView. On Android the WebView widget is backed by a WebView.

2.pubspec.yaml添加依赖

1
  webview_flutter: ^4.7.0

3.示例

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
 import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebviewWidget extends StatefulWidget {
  final String url;

  const WebviewWidget({super.key, required this.url});

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

class WebviewWidgetState extends State<WebviewWidget> {
  late WebViewController _webViewController;
  late String pageTitle = '';

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

    _webViewController = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {},
        onProgress: (progress) {},
        onPageFinished: (url) {
          updatePageTitle();
        },
        onHttpAuthRequest: (request) {},
        onWebResourceError: (error) {
          debugPrint('''
                Page resource error:
                  code: ${error.errorCode}
                  description: ${error.description}
                  errorType: ${error.errorType}
                  isForMainFrame: ${error.isForMainFrame}
                          ''');
        },
        onNavigationRequest: (request) {
          debugPrint('allowing navigation to ${request.url}');

          return NavigationDecision.navigate;
        },
        onUrlChange: (change) {
          debugPrint('url change to ${change.url}');
        },
      ))
      ..addJavaScriptChannel(
        'Toaster',
        onMessageReceived: (p0) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text(p0.message)),
          );
        },
      );
    
    loadHttpRequest(widget.url);
  }

  void updatePageTitle() {
    _webViewController.getTitle().then((value) {
      setState(() {
        if (value != null) {
          pageTitle = value;
        }
      });
    });
  }

  //当 canPop 为 true,则系统返回手势将导致封闭的 Navigator 照常接收弹出。会调用 onPopInvoked,此时didPop为true。
  //当 canPop 为 false,则系统返回手势不会将路由从封闭的 Navigator 中弹出,但仍然会调用 onPopInvoked 方法,此时 didPop 为 false,此时进行逻辑判断或者插入其他需要执行的代码,如果需要返回则再执行 Navigator.of(context).pop();
  //注意此时 onPopInvoked 又会被再次调用,但此时 didPop 为 true。
  //因此,在onPopInvoked中,需要判断一下 didPop,如果为 true, 则 return。

  @override
  Widget build(BuildContext context) {
    return PopScope(
      canPop: false,
      onPopInvoked: (didPop) async {
        if (didPop) {
          return;
        }

        if (await _webViewController.canGoBack()) {
          await _webViewController.goBack();
          updatePageTitle();
        } else {
          if (!context.mounted) {
            return;
          }
          Navigator.of(context).pop();
        }
      },
      child: Scaffold(
        backgroundColor: Colors.green,
        appBar: AppBar(
          title: Text(pageTitle),
        ),
        body: WebViewWidget(controller: _webViewController),
        floatingActionButton: favoriteButton(),
      ),
    );
  }

  Widget favoriteButton() {
    return FloatingActionButton(
      onPressed: () async {
        final String? url = await _webViewController.currentUrl();
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('收藏 $url')),
          );
        }
      },
      child: const Icon(Icons.favorite),
    );
  }

  Future<void> loadHttpRequest(String url) async {
    await _webViewController.loadRequest(Uri.parse(url));
  }
}