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"),
      ),
    ),
  },
);

可选参数 hiddeninitialChild 可以用来显示等待页面加载时的其他内容。如果将 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 交互、添加导航控制等。你可以参考插件的官方文档获取更多详细信息。

回到顶部