如何在 Flutter 中添加 Webview?

Posted

技术标签:

【中文标题】如何在 Flutter 中添加 Webview?【英文标题】:How to add a Webview in Flutter? 【发布时间】:2017-09-25 07:34:09 【问题描述】:

我知道可以将 WebView 添加为整页,但找不到任何示例代码来执行此操作。我假设您可以使用 PageView 作为它的基础,但不确定如何调用本机 android WebView 并将其添加到 PageView。

谁能指出我正确的方向?

【问题讨论】:

【参考方案1】:

您可以使用https://pub.dartlang.org/packages/webview_flutter

例子

import 'package:webview_flutter/webview_flutter.dart';

return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView example'),
      ),
      body: const WebView(
        initialUrl: 'https://flutter.io',
        javascriptMode: JavascriptMode.unrestricted,
      ),
    );

【讨论】:

这可能是值得一去的,遗憾的是它仍在开发者预览版中。 重要提示: 键盘不会在 Android 上显示(参见问题 #19718)。如果您尝试将其用于 OAuth,这是一个很好的选择。如果您需要此功能,请对该问题进行投票,也许它会被重新确定优先级,以便在 2019 年 10 月的当前里程碑之前尽快修复。【参考方案2】:

Flutter 没有对嵌入式 WebView 的内置支持。关注issue 730 获取更新。

您仍然可以在您的应用中显示 Web 内容,但您必须使用插件系统离开 Flutter-land。

如果你只是想打开一个浏览器,可以使用url_launcherFlutter插件。

如果你想做一些更有趣的事情(也许你不想要一个可见的地址栏),你可以实现一个自定义 UIViewController (ios example) 和 Activity (Android example) 并使用plugin API 来启动进入这些。

【讨论】:

没用过这个,但它可能就是这么做的:pub.dartlang.org/packages/flutter_webview_plugin【参考方案3】:

您可以使用下面的 dart 插件来显示 Webview。此外,您可以从这个 url 找到 dart 插件:https://pub.dartlang.org/packages/flutter_webview_plugin

new MaterialApp(
      routes: 
        "/": (_) => new WebviewScaffold(
          url: "https://www.google.com",
          appBar: new AppBar(
            title: new Text("Widget webview"),
          ),
        ),
      ,
    );

【讨论】:

在我看来,这个比webview_flutter 好用。它在显示键盘时没有问题,并且我没有遇到webview_flutter 在单击下拉菜单时造成的一些崩溃。【参考方案4】:

webview plugin 运行良好,但是它将在您的应用程序的每一位顶部创建,因此您必须添加额外的逻辑来显示和隐藏插件。您可以将其全屏显示或显示为一个大小合适的矩形。

https://pub.dartlang.org/packages/flutter_webview_plugin

【讨论】:

【参考方案5】:

在 pubspec.yml 文件中添加依赖:

webview_flutter: ^0.1.1

对于 ios App 下面的键粘贴到 ios 项目文件夹内的 .plist 文件中

<key>io.flutter.embedded_views_preview</key><string>yes</string>
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
</dict>

这是类代码:

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

class WebViewClass extends StatefulWidget 
  @override
  _WebViewClassState createState() => _WebViewClassState();


class _WebViewClassState extends State<WebViewClass> 
  Completer<WebViewController> _controller = Completer<WebViewController>();

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: const Text('WebView'),
      ),
      body: WebView(
        initialUrl: 'https://google.com',
        onWebViewCreated: (WebViewController webViewController) 
          _controller.complete(webViewController);
        ,
      ),
    );
  

【讨论】:

嗨!感谢您的建议,但它现在仍然有效:不支持的操作:尝试使用 TargetPlatform.macOS 的默认 webview 实现,但没有默认的实现【参考方案6】:

您可以使用 Flutter webview 插件。这是插件的网址https://pub.dartlang.org/packages/webview_flutter

带有 CircularProgressIndicator 的 Webview 这是一些屏幕截图。 Before After

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

class WebView extends StatefulWidget 
  @override
  _WebViewState createState() => _WebViewState();


class _WebViewState extends State<WebView> 

  final Completer<WebViewController> _controller =
      Completer<WebViewController>();

  num _stackToView = 1;

  void _handleLoad(String value) 
    setState(() 
      _stackToView = 0;
    );
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
        appBar: AppBar(
          leading: Builder(builder: (BuildContext context) 
            return IconButton(
              icon: Icon(Icons.volume_up, color: Colors.black,),
              onPressed: () 
                Navigator.pop(context);
              ,
            );
          ),
          backgroundColor: Colors.white10,
          elevation: 0,
        ),
        body: IndexedStack(
          index: _stackToView,
          children: [
            Column(
              children: <Widget>[
                Expanded(
                    child: WebView(
                  initialUrl: "https://www.google.co.in/",
                  javascriptMode: JavascriptMode.unrestricted,
                  onPageFinished: _handleLoad,
                  onWebViewCreated: (WebViewController webViewController) 
                    _controller.complete(webViewController);
                  ,
                )),
              ],
            ),
            Container(
              child: Center(child: CircularProgressIndicator(),)
            ),
          ],
        ));
  

【讨论】:

【参考方案7】:

您可以使用flutter_inappwebview插件,这是一个Flutter插件,允许您添加与小部件树集成的内联webviews或打开应用内浏览器窗口!与其他 webview 插件相比,它提供了很多事件、方法和选项!

主要类:

InAppWebView:Flutter Widget 用于添加 内联原生 WebView 集成到 Flutter 小部件树中。要在 iOS 上使用 InAppWebView 类,您需要通过向应用程序的 Info.plist 文件添加一个布尔属性(键为 io.flutter.embedded_views_preview 和值 YES)来选择嵌入视图预览。 ContextMenu:这个类代表 WebView 上下文菜单。 HeadlessInAppWebView:代表无头模式下的 WebView 的类。它可用于在后台运行 WebView,而无需将 InAppWebView 附加到小部件树。 InAppBrowser:使用原生 WebView 的应用内浏览器。 ChromeSafariBrowser:应用内浏览器在 Android 上使用 Chrome Custom Tabs / 在 iOS 上使用 SFSafariViewController。 InAppLocalhostServer:这个类允许你在http://localhost:[port]/上创建一个简单的服务器。默认port 值为8080。 CookieManager:这个类实现了一个单例对象(共享实例),它管理 WebView 实例使用的 cookie。 HttpAuthCredentialDatabase:该类实现了一个管理共享 HTTP 身份验证凭据缓存的单例对象(共享实例)。 WebStorageManager:这个类实现了一个单例对象(共享实例),它管理 WebView 实例使用的网络存储。

这是一个将 WebView 显示为整页的示例:

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(
                    initialUrl: "https://flutter.dev/",
                    initialOptions: InAppWebViewGroupOptions(
                        crossPlatform: InAppWebViewOptions(
                          debuggingEnabled: true,
                        )
                    ),
                    onWebViewCreated: (InAppWebViewController controller) 
                      _webViewController = controller;
                    ,
                    onLoadStart: (InAppWebViewController controller, String url) 

                    ,
                    onLoadStop: (InAppWebViewController controller, String url) 

                    ,
                ),
              ),
            ])),
      ),
    );
  

截图:

【讨论】:

【参考方案8】:

因为 Android 9 中禁止使用“http”

你可以设置:

在您的 android>app>src>主文件夹中导航到 AndroidManifest.xml

   <application
    android:name="io.flutter.app.FlutterApplication"
    android:icon="@mipmap/ic_launcher"
    android:usesCleartextTraffic="true" />

Android 9 上的 Flutter WebView 插件错误

【讨论】:

【参考方案9】:

如果您在将其添加到您的应用时遇到问题,这里是完整的代码:

将 webview_flutter 添加到包的 pubspec.yaml 文件中,就在依赖项下:

pubspec.yaml:

dependencies:
  webview_flutter: 

main.dart:

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: const WebView(
          initialUrl: 'https://flutter.io',
          javascriptMode: JavascriptMode.unrestricted,
        ),
      )
    );
  

【讨论】:

以上是关于如何在 Flutter 中添加 Webview?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Webview - 如何在页面上添加更多链接或元素?

如何在 Flutter 的 webview 中隐藏页眉和页脚。?

如何在 Flutter 应用中添加桌面版网站?

在 webview_flutter 中启用捏合和缩放,在哪里添加代码片段 [this.webView.getSettings().setBuiltInZoomControls(true);]

如果在 WebView Flutter 中导航失败,则重新加载页面

如何在 Flutter 中重新加载 webview?