Flutter InAppWebView.

什么是 flutter_inappwebview ? 这是一个Flutter插件,它允许你将 WebView小部件 整合到你的Flutter应用中,使用 无头WebViews ,或者使用 In-App浏览器

那么, webview_flutter (官方flutter插件)和 flutter_webview_plugin 有什么区别呢?

与其他所有WebView插件相比,它的 功能很丰富 :有很多 事件 方法 选项 来控制WebViews。此外,他们并没有很好的关于他们的API的文档,或者说,至少是不完整的。相反, flutter_inappwebview 的每一个功能几乎都有文档可查(只要查看 pub.dev上的API Reference )。

在这篇文章中,我将介绍人们在flutter_inappwebview官方仓库(issue部分)和StackOverflow上询问的 InAppWebView 小部件的主要类和一些例子。

这是一个插件提供的主要类的列表。

  • InAppWebView : Flutter Widget,用于添加一个集成到flutter widget树中的内嵌式本地WebView。
  • ContextMenu 。该类表示WebView的上下文菜单。
  • HeadlessInAppWebView 。代表无头模式的WebView的类。它可以用来在后台运行WebView,而不需要将InAppWebView附加到widget树中。
  • InAppBrowser :使用原生WebView的In-App浏览器。使用原生WebView的In-App浏览器。
  • ChromeSafariBrowser :使用 Chrome自定义标签 的应用内浏览器。在Android上使用Chrome自定义标签/在iOS上使用 SFSafariViewController 的In-App浏览器。
  • InAppLocalhostServer :该类允许你创建一个简单的应用程序浏览器,在Android上使用Chrome自定义标签,在iOS上使用SFSafariViewController。该类允许你在 http://localhost:[port]/上创建一个简单的服务器。默认端口值为8080。
  • CookieManager :该类实现了一个单人对象。该类实现了一个单人对象(共享实例),用于管理WebView实例使用的Cookie。
  • HttpAuthCredentialDatabase 。这个类实现了一个单人对象(共享实例),它管理共享的HTTP auth凭证缓存。
  • WebStorageManager :该类实现了一个单人对象(共享实例),用于管理共享的HTTP authentials缓存。这个类实现了一个单子对象(共享实例),它管理WebView实例使用的Web存储。
  • 在这篇文章中,我将特别展示 InAppWebView 小部件,那是最常用/最需要的一个。

    InAppWebView是一个和其他Widget一样的Widget!

    InAppWebView 小部件添加到你的应用程序中是非常简单的。它只是一个像任何其他Flutter小部件一样的小部件。 InAppWebView(initialUrl: 'https://github.com/flutter')

    注意 :要在iOS上使用它,你需要通过在应用程序的 Info.plist 文件中添加一个布尔属性来选择嵌入式视图预览,其键为 io.flutter.embedded_views_preview ,值为YES。

    这个widget有一组初始属性,你可以用它来初始化WebView。

  • initialUrl : 将被加载的初始URL。
  • initialOptions :将被加载的初始URL; initialOptions:将被使用的初始WebView选项。将要使用的初始WebView选项。
  • gestureRecognizers :指定哪些手势应该被WebView消耗。
  • initialData :初始InAppWebViewInitial数据。将要加载的InAppWebViewInitialData的初始数据,比如一个HTML字符串。
  • initialFile :将被加载的初始资产文件(查看 " 加载资产文件夹内的文件 "部分)。
  • initialHeaders : 将要使用的初始头文件。将要使用的初始头文件。
  • contextMenu :上下文菜单,包含自定义菜单项。上下文菜单,包含自定义菜单项。
  • 所有可用的WebView选项列表相当长,例如,您可以使用 javascriptEnabled 选项启用/禁用JavaScript,或使用 cacheEnabled 选项启用/禁用缓存。所有选项的完整列表可以在 这里 找到。

    使用InAppWebViewController来控制你的WebView。

    相反,为了控制WebView,你有 InAppWebViewController 类。当WebView准备好使用时,这个控制器由 onWebViewCreated 回调返回。

    通过它,你可以控制你的WebView或者访问它的属性,比如使用 getUrl 方法访问当前的URL。其他方法,例如, loadUrl 加载一个新的URL, postUrl 使用POST方法加载一个给定的带有自定义数据的URL, evaluationJavascript 评估JavaScript代码到WebView中,并得到评估结果, takeScreenshot 拍摄WebView可见视口的截图(PNG格式), getCertificate 获取主顶层页面的SSL证书,如果没有证书则为 null 。你可以使用的所有方法的完整列表相当长,可以在 这里 找到。

    InAppWebView事件

    InAppWebView 小部件提供了 各种事件 ! 下面是其中的几个事件。

  • onLoadStart :当WebView开始加载一个URL时被触发的事件。
  • onLoadStop :当WebView完成加载一个URL时触发的事件。
  • onLoadHttpError :当WebView主页面收到一个HTTP错误时被触发的事件。
  • onConsoleMessage :当WebView收到JavaScript控制台消息(如 console.log console.error 等)时触发的事件。
  • shouldOverrideUrlLoading :当当前WebView中的URL即将被加载时,给主机应用程序一个控制的机会。
  • onDownloadStart :当WebView识别到一个可下载的文件时发射的事件。
  • onReceivedHttpAuthRequest :当WebView接收到HTTP认证请求时触发的事件。默认行为是取消该请求。
  • onReceivedServerTrustAuthRequest :当WebView需要执行服务器信任认证(证书验证)时被触发的事件。
  • onPrint :当 window.print() 从JavaScript端被调用时被触发的事件,默认行为是取消请求;onCreateWindow:当WebView需要进行服务器信任验证(证书验证)时被触发的事件。
  • onCreateWindow : 当InAppWebView请求主机应用程序创建一个新窗口时,例如当试图打开一个 target="_blank" 的链接或当 window.open() 被JavaScript端调用时,事件被触发。
  • 还有很多很多 我建议查看API参考资料来了解更多细节。至于WebView的选项和方法,所有WebView事件的完整列表相当长,可以在 这里 找到。

    InAppWebView简单示例

    这是一个简单的例子,显示了一个 InAppWebView 小组件,它的当前URL和3个按钮:一个是返回,一个是前进,另一个是重新加载当前页面。

    InAppWebView的例子。

    这是完整的代码示例。

    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      runApp(new MyApp());
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => new _MyAppState();
    class _MyAppState extends State<MyApp> {
      InAppWebViewController _webViewController;
      String url = "";
      double progress = 0;
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('InAppWebView Example'),
            body: Container(
                child: Column(children: <Widget>[
                  Container(
                    padding: EdgeInsets.all(20.0),
                    child: Text(
                        "CURRENT URL\n${(url.length > 50) ? url.substring(0, 50) + "..." : url}"),
                  Container(
                      padding: EdgeInsets.all(10.0),
                      child: progress < 1.0
                          ? LinearProgressIndicator(value: progress)
                          : Container()),
                  Expanded(
                    child: Container(
                      margin: const EdgeInsets.all(10.0),
                      decoration:
                      BoxDecoration(border: Border.all(color: Colors.blueAccent)),
                      child: InAppWebView(
                        initialUrl: "https://flutter.dev/",
                        initialOptions: InAppWebViewGroupOptions(
                            crossPlatform: InAppWebViewOptions(
                              debuggingEnabled: true,
                        onWebViewCreated: (InAppWebViewController controller) {
                          _webViewController = controller;
                        onLoadStart: (InAppWebViewController controller, String url) {
                          setState(() {
                            this.url = url;
                        onLoadStop: (InAppWebViewController controller, String url) async {
                          setState(() {
                            this.url = url;
                        onProgressChanged: (InAppWebViewController controller, int progress) {
                          setState(() {
                            this.progress = progress / 100;
                  ButtonBar(
                    alignment: MainAxisAlignment.center,
                    children: <Widget>[
                      RaisedButton(
                        child: Icon(Icons.arrow_back),
                        onPressed: () {
                          if (_webViewController != null) {
                            _webViewController.goBack();
                      RaisedButton(
                        child: Icon(Icons.arrow_forward),
                        onPressed: () {
                          if (_webViewController != null) {
                            _webViewController.goForward();
                      RaisedButton(
                        child: Icon(Icons.refresh),
                        onPressed: () {
                          if (_webViewController != null) {
                            _webViewController.reload();
    

    JavaScript处理程序(通道)

    你可以和JavaScript端进行通信,反之亦然。要添加一个JavaScript处理程序,可以使用_webViewController.addJavaScriptHandler方法,在该方法中定义了handlerName和一个callback,当它被JavaScript端调用时,就会被调用。回调可以返回JavaScript端要发送的数据。

    而在JavaScript端,要执行回调处理程序并向Flutter发送数据,则需要使用window.flutter_inappwebview.callHandler(handlerName <String>,...args)方法,其中handlerName是一个字符串,代表你调用的处理程序名称,args是你可以向Flutter端发送的可选参数。

    为了正确调用window.flutter_inappwebview.callHandler(handlerName <String>, ...args),你需要等待并监听JavaScript事件flutterInAppWebViewPlatformReady。一旦平台(Android或iOS)准备好处理callHandler方法,这个事件就会被派发。

    下面是一个例子。

    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      runApp(new MyApp());
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => new _MyAppState();
    class _MyAppState extends State<MyApp> {
      InAppWebViewController _webViewController;
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('InAppWebView Example'),
            body: Container(
                child: Column(children: <Widget>[
                  Expanded(
                    child:InAppWebView(
                        initialData: InAppWebViewInitialData(
                          data: """
    <!DOCTYPE html>
    <html lang="en">
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        </head>
            <h1>JavaScript Handlers (Channels) TEST</h1>
            <script>
                window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
                    window.flutter_inappwebview.callHandler('handlerFoo')
                      .then(function(result) {
                        // print to the console the data coming
                        // from the Flutter side.
                        console.log(JSON.stringify(result));
                        window.flutter_inappwebview
                          .callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}, result);
            </script>
        </body>
    </html>
                        initialOptions: InAppWebViewGroupOptions(
                            crossPlatform: InAppWebViewOptions(
                              debuggingEnabled: true
    
    
    
    
        
    ,
                        onWebViewCreated: (InAppWebViewController controller) {
                          _webViewController = controller;
                          _webViewController.addJavaScriptHandler(handlerName:'handlerFoo', callback: (args) {
                            // return data to JavaScript side!
                            return {
                              'bar': 'bar_value', 'baz': 'baz_value'
                          _webViewController.addJavaScriptHandler(handlerName: 'handlerFooWithArgs', callback: (args) {
                            print(args);
                            // it will print: [1, true, [bar, 5], {foo: baz}, {bar: bar_value, baz: baz_value}]
                        onConsoleMessage: (controller, consoleMessage) {
                          print(consoleMessage);
                          // it will print: {message: {"bar":"bar_value","baz":"baz_value"}, messageLevel: 1}
    

    InAppWebView中的WebRTC

    目前,WebRTC只在Android上支持,因为不幸的是,在iOS上WKWebView并没有实现所有的WebRTC API(你可以关注这个问题:#200)。

    我将使用appr.tc/ 来展示一个测试WebRTC功能的例子。这是一个基于WebRTC的视频聊天演示应用(github.com/webrtc/appr…

    要请求关于摄像头和麦克风的权限,你可以使用 permission_handler 插件。另外,你需要将WebView选项mediaPlaybackRequiresUserGesture设置为false,才能自动播放HTML5音频和视频。

    此外,在Android上,你需要实现androidOnPermissionRequest事件(这是一个Android特有的事件),也就是当WebView请求访问特定资源的权限时,会被触发的事件(也就是Android原生WebChromeClient.onPermissionRequest事件)。在这种情况下,该事件用于授予WebRTC API的权限。此外,你还需要在AndroidManifest.xml中添加这些权限。

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.VIDEO_CAPTURE" />
    <uses-permission android:name="android.permission.AUDIO_CAPTURE" />
    

    WebRTC的例子。

    下面是完整的代码示例。

    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    import 'package:permission_handler/permission_handler.dart';
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Permission.camera.request();
      await Permission.microphone.request();
      runApp(MyApp());
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => new _MyAppState();
    class _MyAppState extends State<MyApp> {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: InAppWebViewPage()
    class InAppWebViewPage extends StatefulWidget {
      @override
      _InAppWebViewPageState createState() => new _InAppWebViewPageState();
    class _InAppWebViewPageState extends State<InAppWebViewPage> {
      InAppWebViewController _webViewController;
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text("InAppWebView")
            body: Container(
                child: Column(children: <Widget>[
                  Expanded(
                    child: Container(
                      child: InAppWebView(
                          initialUrl: "https://appr.tc/r/704328056",
                          initialOptions: InAppWebViewGroupOptions(
                            crossPlatform: InAppWebViewOptions(
                              mediaPlaybackRequiresUserGesture: false,
                              debuggingEnabled: true,
                          onWebViewCreated: (InAppWebViewController controller) {
                            _webViewController = controller;
                          androidOnPermissionRequest: (InAppWebViewController controller, String origin, List<String> resources) async {
                            return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
    

    如何在InAppWebView中启用下载文件的功能

    InAppWebView可以识别Android和iOS平台上的可下载文件。为了能够识别可下载文件,你需要设置useOnDownloadStart: true选项,然后你就可以监听onDownloadStart事件。

    在Android平台上,你需要在你的AndroidManifest.xml文件里面添加写权限。

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    然后,你需要使用 permission_handler 插件询问权限。相反,为了有效下载你的文件,你可以使用flutter_downloader插件。

    这里是一个完整的例子,使用ovh.net/files/(特别是h… 作为URL)来测试下载。

    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    import 'package:flutter_downloader/flutter_downloader.dart';
    import 'package:path_provider/path_provider.dart';
    import 'package:permission_handler/permission_handler.dart';
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await FlutterDownloader.initialize(
          debug: true // optional: set false to disable printing logs to console
      await Permission.storage.request();
      runApp(MyApp());
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => new _MyAppState();
    class _MyAppState extends State<MyApp> {
      InAppWebViewController _webViewController;
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('InAppWebView Example'),
            body: Container(
                child: Column(children: <Widget>[
                  Expanded(
                      child: InAppWebView(
                        initialUrl: "http://ovh.net/files/1Mio.dat",
                        initialOptions: InAppWebViewGroupOptions(
                          crossPlatform: InAppWebViewOptions(
                              debuggingEnabled: true,
                              useOnDownloadStart: true
                        onWebViewCreated: (InAppWebViewController controller) {
                          _webViewController = controller;
                        onDownloadStart: (controller, url) async {
                          print("onDownloadStart $url");
                          final taskId = await FlutterDownloader.enqueue(
                            url: url,
                            savedDir: (await getExternalStorageDirectory()).path,
                            showNotification: true, // show download progress in status bar (for Android)
                            openFileFromNotification: true, // click on notification to open downloaded file (for Android)
    

    正如你所看到的,我也使用path_provider插件来获取我想保存文件的文件夹。

    允许使用自签名的SSL证书

    要允许自签名的SSL证书,你可以使用onReceivedServerTrustAuthRequest事件,然后简单地返回继续请求。

    onReceivedServerTrustAuthRequest: (controller, challenge) async {
      return ServerTrustAuthResponse(action: ServerTrustAuthResponseAction.PROCEED);
    

    如何管理用target="_blank "或 "window.open "打开的弹出窗口。

    当用户点击target="_blank "的链接或通过使用window.open的JavaScript代码来管理弹出窗口时,你可以使用onCreateWindow事件。在Android上,为了能够允许这个事件,你需要将supportMultipleWindows选项设置为true。另外,为了能够允许使用JavaScript,你需要将javaScriptCanOpenWindowsAutomatically设置为true。

    如果你想管理这些请求,你应该从这个事件中返回true,否则,这个事件的默认实现什么也不做,因此返回false

    CreateWindowRequest代表导航请求,它包含一个windowId,可以用来创建,例如,一个新的InAppWebView实例。这个windowId被本地代码用来映射该请求和用于管理该请求的WebView。 另外,CreateWindowRequest包含了请求的url(在Android上,如果弹出窗口是用window.open的JavaScript打开的,它将是null),但是如果你需要维护Window JavaScript对象引用(用window.open方法创建的),例如,调用window.close方法,那么你应该用windowId创建新的WebView,而不使用url。 下面是一个简单的例子,当用户点击链接时,会显示一个AlertDialog

    import 'dart:async';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      runApp(new MyApp());
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => new _MyAppState();
    class _MyAppState extends State<MyApp> {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: InAppWebViewPage()
    class InAppWebViewPage extends StatefulWidget {
      @override
      _InAppWebViewPageState createState() => new _InAppWebViewPageState();
    class _InAppWebViewPageState extends State<InAppWebViewPage> {
      InAppWebViewController _webViewController;
      InAppWebViewController _webViewPopupController;
      @override
      void initState() {
        super.initState();
      @override
      void dispose() {
        super.dispose();
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('InAppWebView Example'),
            body: SafeArea(
              child: Container(
                  child: InAppWebView(
                    initialData: InAppWebViewInitialData(
                        data: """
    <!DOCTYPE html>
    <html lang="en">
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Flutter InAppWebView</title>
    </head>
      <a style="margin: 50px; background: #333; color: #fff; font-weight: bold; font-size: 20px; padding: 15px; display: block;"
        href="https://github.com/flutter"
        target="_blank">
        Click here to open https://github.com/flutter in a popup!
    </body>
    </html>
                    initialOptions: InAppWebViewGroupOptions(
                        crossPlatform: InAppWebViewOptions(
                          debuggingEnabled: true,
                          // set this to true if you are using window.open to open a new window with JavaScript
                          javaScriptCanOpenWindowsAutomatically: true
                        android: AndroidInAppWebViewOptions(
                          // on Android you need to set supportMultipleWindows to true,
                          // otherwise the onCreateWindow event won't be called
                          supportMultipleWindows: true
                    onWebViewCreated: (InAppWebViewController controller) {
                      _webViewController = controller;
                    onCreateWindow: (controller, createWindowRequest) async {
                      print("onCreateWindow");
                      showDialog(
                        context: context,
                        builder: (context) {
                          return AlertDialog(
                            content: Container(
                              width: MediaQuery.of(context).size.width,
                              height: 400,
                              child: InAppWebView(
                                // Setting the windowId property is important here!
                                windowId: createWindowRequest.windowId,
                                initialOptions: InAppWebViewGroupOptions(
                                    crossPlatform: InAppWebViewOptions(
                                        debuggingEnabled: true,
                                onWebViewCreated: (InAppWebViewController controller) {
                                  _webViewPopupController = controller;
                                onLoadStart: (InAppWebViewController controller, String url) {
                                  print("onLoadStart popup $url");
                                onLoadStop: (InAppWebViewController controller, String url) {
                                  print("onLoadStop popup $url");
                      return true;
    

    onCreateWindow事件 - 弹出窗口示例。

    管理平台URL,如whatsapp:、fb:、tel:、mailto:等。

    一般情况下,WebView不知道如何管理whatsapp:tel:fb:协议/scheme: ,tel:或fb:协议/scheme。为了捕获这些自定义协议/scheme的请求,你可以使用shouldOverrideUrlLoading事件(你需要用useShouldOverrideUrlLoading: true选项启用它)。 这样你就可以取消对WebView的请求,而是打开App,例如,使用url_launcher插件。

    initialOptions: InAppWebViewGroupOptions(
      crossPlatform: InAppWebViewOptions(
          debuggingEnabled: true,
          useShouldOverrideUrlLoading: true
    shouldOverrideUrlLoading: (controller, request) async {
      var url = request.url;
      var uri = Uri.parse(url);
      if (!["http", "https", "file",
        "chrome", "data", "javascript",
        "about"].contains(uri.scheme)) {
        if (await canLaunch(url)) {
          // Launch the App
          await launch(
          // and cancel the request
          return ShouldOverrideUrlLoadingAction.CANCEL;
      return ShouldOverrideUrlLoadingAction.ALLOW;
    

    管理WebView Cookies

    要管理WebView cookie,可以使用CookieManager类,它实现了一个单人对象(共享实例)。在 Android 上,它是使用 CookieManager 类实现的。在iOS上,它是使用WKHTTPCookieStore类实现的。

    下面是一个如何设置cookie的例子。

    CookieManager _cookieManager = CookieManager.instance();
    final expiresDate =
        DateTime.now().add(Duration(days: 3)).millisecondsSinceEpoch;
    _cookieManager.setCookie(
      url: "https://flutter.dev/",
      name: "session",
      value: "54th5hfdcfg34",
      domain: ".flutter.dev",
      expiresDate: expiresDate,
      isSecure: true,
    

    自定义上下文菜单

    您可以自定义WebView的上下文菜单,添加自定义菜单项,和/或隐藏默认的系统菜单项。对于每个自定义菜单项,你可以声明一个回调action,当用户点击它时,就会被调用。举个例子,我将添加一个名为Special的自定义菜单项,并定义一个回调动作,在用户选择文本时向用户显示一个JavaScript window.alert

    自定义菜单项的例子。

    这里是完整的代码示例。

    import 'dart:async';
    import 'dart:io';
    import 'package:flutter/material.dart';
    import 'package:flutter_inappwebview/flutter_inappwebview.dart';
    Future main() async {
      WidgetsFlutterBinding.ensureInitialized();
      runApp(MyApp());
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => new _MyAppState();
    class _MyAppState extends State<MyApp> {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
            home: InAppWebViewPage()
    class InAppWebViewPage extends StatefulWidget {
      @override
      _InAppWebViewPageState createState() => new _InAppWebViewPageState();
    class _InAppWebViewPageState extends State<InAppWebViewPage> {
      InAppWebViewController _webViewController;
      ContextMenu contextMenu;
      @override
      void initState() {
        super.initState();
        contextMenu = ContextMenu(
            menuItems: [
              ContextMenuItem(androidId: 1, iosId: "1", title: "Special", action: () async {
                print("Menu item Special clicked!");
                var selectedText = await _webViewController.getSelectedText();
                await _webViewController.clearFocus();
                await _webViewController.evaluateJavascript(source: "window.alert('You have selected: $selectedText')");
            options: ContextMenuOptions(
                hideDefaultSystemContextMenuItems: false
            onCreateContextMenu: (hitTestResult) async {
              print("onCreateContextMenu");
              print(hitTestResult.extra);
              print(await _webViewController.getSelectedText());
            onHideContextMenu: () {
              print("onHideContextMenu");
            onContextMenuActionItemClicked: (contextMenuItemClicked) async {
              var id = (Platform.isAndroid) ? contextMenuItemClicked.androidId : contextMenuItemClicked.iosId;
              print("onContextMenuActionItemClicked: " + id.toString() + " " + contextMenuItemClicked.title);
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
                title: Text("InAppWebView")
            body: Container(
                child: Column(children: <Widget>[
                  Expanded(
                    child: Container(
                      child: InAppWebView(
                          initialUrl: "https://github.com/flutter",
                          contextMenu: contextMenu,
                          initialOptions: InAppWebViewGroupOptions(
                            crossPlatform: InAppWebViewOptions(
                              debuggingEnabled: true,
                          onWebViewCreated: (InAppWebViewController controller) {
                            _webViewController = controller;
    

    在这篇文章中,我对flutter_inappwebview插件做了一点介绍,特别是关于InAppWebView小部件的介绍。这个插件正在持续开发中(在写这篇文章的时候,最新的版本是4.0.0),我建议你查看API Reference来了解所有的功能。对于任何新的功能请求/bug修复,你可以使用版本库的问题部分。

    下一篇文章将介绍如何使用这个插件实现一个全功能浏览器在Flutter中使用WebViews创建一个全功能浏览器

    今天的内容就到这里了! 希望它为你的Flutter应用打开了新的用例。

    www.twitter.com/FlutterComm

    通过www.DeepL.com/Translator(免费版)翻译

    分类:
    前端
    标签: