Flutter网页视图展示插件flutter_webview_plugin_android_v2的使用

Flutter网页视图展示插件flutter_webview_plugin_android_v2的使用

一个允许Flutter与原生WebView进行通信的插件。

注意: WebView并未集成在小部件树中,而是在Flutter视图之上的原生视图。因此,你将无法看到可能与WebView占据的屏幕区域重叠的Snackbar、对话框或其他Flutter小部件。

getSafeAcceptedType() 函数仅适用于最低SDK版本为21。 eval() 函数仅支持SDK版本19或更高的版本来评估JavaScript。

开始使用

对于如何开始使用Flutter,可以查看我们的在线文档。

iOS

为了让插件正确工作,你需要在 ios/Runner/Info.plist 文件中添加新的键:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
</dict>

NSAllowsArbitraryLoadsInWebContent 用于iOS 10及以上版本,NSAllowsArbitraryLoads 用于iOS 9。

工作原理

使用Flutter导航全屏启动WebView

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

可选参数 hidden 和 initialChild 可以用来显示等待页面加载时的其他内容。如果将 hidden 设置为 true,它将显示一个默认的 CircularProgressIndicator。如果你指定了一个Widget作为 initialChild,你可以自定义等待页面加载时显示的内容。

例如,以下代码将在页面加载前显示一个带有文本 “Waiting…” 的红色背景屏幕。

return new MaterialApp(
  title: 'Flutter WebView Demo',
  theme: new ThemeData(
    primarySwatch: Colors.blue,
  ),
  routes: {
    '/': (_) => const MyHomePage(title: 'Flutter WebView Demo'),
    '/widget': (_) => new WebviewScaffold(
      url: selectedUrl,
      appBar: new AppBar(
        title: const Text('Widget webview'),
      ),
      withZoom: true,
      withLocalStorage: true,
      hidden: true,
      initialChild: Container(
        color: Colors.redAccent,
        child: const Center(
          child: Text('Waiting.....'),
        ),
      ),
    ),
  },
);

FlutterWebviewPlugin 提供了一个单例实例,该实例与唯一的WebView相关联,因此你可以在应用的任何地方控制WebView。

监听事件:

final flutterWebviewPlugin = new FlutterWebviewPlugin();

flutterWebviewPlugin.onUrlChanged.listen((String url) {

});

监听WebView中的滚动事件

final flutterWebviewPlugin = new FlutterWebviewPlugin();
flutterWebviewPlugin.onScrollYChanged.listen((double offsetY) { // 最新垂直滚动偏移量
  // 在这里比较垂直滚动变化与旧值
});

flutterWebviewPlugin.onScrollXChanged.listen((double offsetX) { // 最新水平滚动偏移量
  // 在这里比较水平滚动变化与旧值
});

注意:请注意,iOS和Android之间的滚动距离略有不同。Android设备的滚动值差异通常比iOS设备大。

隐藏WebView

final flutterWebviewPlugin = new FlutterWebviewPlugin();

flutterWebviewPlugin.launch(url, hidden: true);

关闭已启动的WebView

flutterWebviewPlugin.close();

在自定义矩形区域内显示WebView

final flutterWebviewPlugin = new FlutterWebviewPlugin();

flutterWebviewPlugin.launch(url,
  fullScreen: false,
  rect: new Rect.fromLTWH(
    0.0,
    0.0,
    MediaQuery.of(context).size.width,
    300.0,
  ),
);

向WebView注入自定义代码

使用 flutterWebviewPlugin.evalJavaScript(String code)。此函数必须在页面加载完成后运行(即监听 onStateChanged 事件,当状态为 finishLoad 时)。

如果你需要嵌入大量JavaScript代码,可以使用资源文件。将资源文件添加到 pubspec.yaml 中,然后调用该函数:

Future<String> loadJS(String name) async {
  var givenJS = rootBundle.loadString('assets/$name.js');
  return givenJS.then((String js) {
    flutterWebViewPlugin.onStateChanged.listen((viewState) async {
      if (viewState.type == WebViewState.finishLoad) {
        flutterWebViewPlugin.evalJavascript(js);
      }
    });
  });
}

访问文件系统中的本地文件

在启动函数或WebView支架中将 withLocalUrl 选项设置为 true 以启用对本地URL的支持。

注意,在iOS上,还需要将 localUrlScope 选项设置为目录路径。所有位于此文件夹(或子文件夹)内的文件都将被允许访问。如果省略,则只允许打开的本地文件访问,导致无法加载子资源。此选项在Android上被忽略。

忽略SSL错误

将 ignoreSSLErrors 选项设置为 true 以显示来自通常不受WebView信任的服务器的内容(如自签名证书)。

注意: 不要在生产环境中使用此功能。

在iOS上,你需要在 ios/Runner/Info.plist 文件中添加新的键:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
</dict>

NSAllowsArbitraryLoadsInWebContent 用于iOS 10及以上版本,NSAllowsArbitraryLoads 用于iOS 9。

你可以通过测试是否可以访问不信任SSL证书的页面来验证其是否正常工作,例如通过 https://self-signed.badssl.com/ 进行测试。

WebView事件

  • <Stream<Null>> onDestroy
  • <Stream<String>> onUrlChanged
  • <Stream<WebViewStateChanged>> onStateChanged
  • <Stream<double>> onScrollXChanged
  • <Stream<double>> onScrollYChanged
  • <Stream<String>> onError

注意: 不要忘记释放WebView:

flutterWebviewPlugin.dispose()

WebView函数

Future<Null> launch(String url, {
    Map<String, String> headers: null,
    Set<JavascriptChannel> javascriptChannels: null,
    bool withJavascript: true,
    bool clearCache: false,
    bool clearCookies: false,
    bool hidden: false,
    bool enableAppScheme: true,
    Rect rect: null,
    String userAgent: null,
    bool withZoom: false,
    bool displayZoomControls: false,
    bool withLocalStorage: true,
    bool withLocalUrl: true,
    String localUrlScope: null,
    bool withOverviewMode: false,
    bool scrollBar: true,
    bool supportMultipleWindows: false,
    bool appCacheEnabled: false,
    bool allowFileURLs: false,
    bool useWideViewPort: false,
    String invalidUrlRegex: null,
    bool geolocationEnabled: false,
    bool debuggingEnabled: false,
    bool ignoreSSLErrors: false,
});
Future<String> evalJavascript(String code);
Future<Map<String, dynamic>> getCookies();
Future<Null> cleanCookies();
Future<Null> resize(Rect rect);
Future<Null> show();
Future<Null> hide();
Future<Null> reloadUrl(String url);
Future<Null> close();
Future<Null> reload();
Future<Null> goBack();
Future<Null> goForward();
Future<Null> stopLoading();
Future<bool> canGoBack();
Future<bool> canGoForward();

示例代码

example/lib/main.dart

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _flutterWebviewPlugin = FlutterWebviewPlugin();

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter WebView Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routes: {
        '/': (_) => FutureBuilder<void>(
            future: _flutterWebviewPlugin.hide(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                WidgetsBinding.instance.addPostFrameCallback((_) {
                  _flutterWebviewPlugin.show();
                });
              }
              return WebviewScaffold(
                url: 'https://www.google.com',
                appBar: AppBar(
                  title: const Text('Plugin Example App'),
                ),
                withZoom: true,
                withLocalStorage: true,
                hidden: true,
                initialChild: Container(
                  color: Colors.lightBlueAccent,
                  child: const Center(
                    child: CircularProgressIndicator(color: Colors.white),
                  ),
                ),
              );
            }),
      },
    );
  }
}

更多关于Flutter网页视图展示插件flutter_webview_plugin_android_v2的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网页视图展示插件flutter_webview_plugin_android_v2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何使用 flutter_webview_plugin_android_v2 插件在 Flutter 应用中展示网页视图的代码示例。这个插件允许你在 Flutter 应用中嵌入一个 WebView 来展示网页内容。

首先,确保你在 pubspec.yaml 文件中添加了该插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_webview_plugin_android_v2: ^0.4.4  # 请注意版本号,使用最新版本

然后,运行 flutter pub get 来获取依赖。

接下来是主 Dart 文件的示例代码,用于展示如何使用 flutter_webview_plugin_android_v2:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: WebViewExample(),
    );
  }
}

class WebViewExample extends StatefulWidget {
  @override
  _WebViewExampleState createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
  final FlutterWebviewPlugin flutterWebviewPlugin = FlutterWebviewPlugin();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebView Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            // 打开网页
            await flutterWebviewPlugin.launch(
              url: 'https://www.example.com', // 替换为你想要展示的网页URL
            );
          },
          child: Text('Open WebView'),
        ),
      ),
    );
  }

  @override
  void initState() {
    super.initState();
    // 配置WebView插件(可选)
    flutterWebviewPlugin.configWebViewWithOptions(
      androidWebViewOptions: AndroidWebViewOptions(
        useHybridComposition: true, // 启用Hybrid Composition(适用于Android 12+)
      ),
    );

    // 监听WebView事件(可选)
    flutterWebviewPlugin.onUrlOpened.listen((String url) {
      print("Opened URL: $url");
    });

    flutterWebviewPlugin.onUrlChanged.listen((String url) {
      print("URL Changed: $url");
    });

    flutterWebviewPlugin.onPageFinished.listen((String url) {
      print("Page Finished Loading: $url");
    });

    flutterWebviewPlugin.onPageStarted.listen((String url) {
      print("Page Started Loading: $url");
    });

    flutterWebviewPlugin.onReceivedError.listen((WebViewClientError error) {
      print("Received Error: ${error.errorCode}, ${error.description}");
    });
  }

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

在这个示例中:

  1. 我们导入了 flutter_webview_plugin_android_v2 包。
  2. 创建了一个简单的 Flutter 应用,包含一个按钮。
  3. 点击按钮时,使用 flutterWebviewPlugin.launch 方法打开指定的网页 URL。
  4. 在 initState 方法中,我们配置了 WebView 的一些选项(如 Hybrid Composition),并添加了一些事件监听器来监听 WebView 的不同事件(如页面开始加载、页面加载完成、URL 改变等)。
  5. 在 dispose 方法中,我们调用了 flutterWebviewPlugin.dispose 来释放资源。

请注意,这个示例仅展示了基本的用法。根据需求,你可能需要进一步自定义 WebView 的行为,例如处理 JavaScript 交互、添加导航控制等。你可以参考插件的官方文档获取更多详细信息。

回到顶部