Flutter桌面Web视图插件desktop_webview_window的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter桌面Web视图插件desktop_webview_window的使用

插件概述

desktop_webview_window 是一个用于在Flutter桌面应用程序中显示WebView窗口的插件。它支持Windows、Linux和macOS平台,并依赖于这些平台上相应的WebView库。

快速开始

修改 main 方法

首先需要修改你的 main 方法以确保能够正确初始化 WebView 窗口:

import 'package:desktop_webview_window/desktop_webview_window.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // 如果是WebView标题栏部件,则直接运行它
  if (runWebViewTitleBarWidget(args)) {
    return;
  }

  runApp(MyApp());
}

启动 WebViewWindow

接下来,你可以通过以下代码启动一个WebView窗口并加载指定的URL:

final webview = await WebviewWindow.create();
webview.launch("https://example.com");

Linux 需求

如果你是在Linux环境下开发,你需要安装 webkit2gtk-4.1 库:

sudo apt-get install webkit2gtk-4.1

Windows 注意事项

在Windows上,desktop_webview_window 依赖于WebView2。WebView2 Runtime 已经包含在Windows 11中,但对于Windows 10设备来说可能需要单独安装。可以使用 WebviewWindow.isWebviewAvailable() 来检查WebView2是否可用。

默认情况下,WebView2会将用户数据存储在应用可执行文件同级目录下的 WebView2 文件夹中,这可能会导致问题(例如当应用程序被安装到只读目录时)。因此建议为WebView2指定自定义的用户数据文件夹:

final webview = await WebviewWindow.create(
  configuration: CreateConfiguration(
    userDataFolderWindows: 'your_custom_user_data_folder',
  ),
);

完整示例代码

下面是一个完整的示例代码,展示了如何使用 desktop_webview_window 创建一个带有WebView窗口的应用程序:

import 'dart:io';
import 'package:desktop_webview_window/desktop_webview_window.dart';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';

void main(List<String> args) {
  debugPrint('args: $args');
  if (runWebViewTitleBarWidget(args)) {
    return;
  }
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final TextEditingController _controller = TextEditingController(text: 'https://example.com');
  bool? _webviewAvailable;

  @override
  void initState() {
    super.initState();
    WebviewWindow.isWebviewAvailable().then((value) {
      setState(() {
        _webviewAvailable = value;
      });
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
          actions: [
            IconButton(
              onPressed: () async {
                final webview = await WebviewWindow.create(
                  configuration: CreateConfiguration(
                    windowHeight: 1280,
                    windowWidth: 720,
                    title: "ExampleTestWindow",
                    titleBarTopPadding: Platform.isMacOS ? 20 : 0,
                    userDataFolderWindows: await _getWebViewPath(),
                  ),
                );
                webview
                  ..registerJavaScriptMessageHandler("test", (name, body) {
                    debugPrint('on javaScipt message: $name $body');
                  })
                  ..setApplicationNameForUserAgent(" WebviewExample/1.0.0")
                  ..setPromptHandler((prompt, defaultText) {
                    if (prompt == "test") {
                      return "Hello World!";
                    } else if (prompt == "init") {
                      return "initial prompt";
                    }
                    return "";
                  })
                  ..addScriptToExecuteOnDocumentCreated("""
  const mixinContext = {
    platform: 'Desktop',
    conversation_id: 'conversationId',
    immersive: false,
    app_version: '1.0.0',
    appearance: 'dark',
  }
  window.MixinContext = {
    getContext: function() {
      return JSON.stringify(mixinContext)
    }
  }
""")
                  ..launch("http://localhost:3000/test.html");
              },
              icon: const Icon(Icons.bug_report),
            )
          ],
        ),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                TextField(controller: _controller),
                const SizedBox(height: 16),
                TextButton(
                  onPressed: _webviewAvailable != true ? null : _onTap,
                  child: const Text('Open'),
                ),
                const SizedBox(height: 20),
                TextButton(
                  onPressed: () async {
                    await WebviewWindow.clearAll(userDataFolderWindows: await _getWebViewPath());
                    debugPrint('clear complete');
                  },
                  child: const Text('Clear all'),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }

  void _onTap() async {
    final webview = await WebviewWindow.create(
      configuration: CreateConfiguration(
        userDataFolderWindows: await _getWebViewPath(),
        titleBarTopPadding: Platform.isMacOS ? 20 : 0,
      ),
    );
    webview
      ..setBrightness(Brightness.dark)
      ..setApplicationNameForUserAgent(" WebviewExample/1.0.0")
      ..launch(_controller.text)
      ..addOnUrlRequestCallback((url) {
        debugPrint('url: $url');
        final uri = Uri.parse(url);
        if (uri.path == '/login_success') {
          debugPrint('login success. token: ${uri.queryParameters['token']}');
          webview.close();
        }
      })
      ..onClose.whenComplete(() {
        debugPrint("on close");
      });
    await Future.delayed(const Duration(seconds: 2));
    for (final javaScript in _javaScriptToEval) {
      try {
        final ret = await webview.evaluateJavaScript(javaScript);
        debugPrint('evaluateJavaScript: $ret');
      } catch (e) {
        debugPrint('evaluateJavaScript error: $e \n $javaScript');
      }
    }
  }
}

const _javaScriptToEval = [
  """
  function test() {
    return;
  }
  test();
  """,
  'eval({"name": "test", "user_agent": navigator.userAgent})',
  '1 + 1',
  'undefined',
  '1.0 + 1.0',
  '"test"',
];

Future<String> _getWebViewPath() async {
  final document = await getApplicationDocumentsDirectory();
  return p.join(document.path, 'desktop_webview_window');
}

这个例子展示了如何创建一个简单的Flutter桌面应用,并在其内部集成WebView窗口。同时,它还演示了如何处理一些常见的WebView功能,如设置用户代理字符串、监听URL请求、执行JavaScript等。


更多关于Flutter桌面Web视图插件desktop_webview_window的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter桌面Web视图插件desktop_webview_window的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter桌面应用中使用desktop_webview_window插件的示例代码。这个插件允许你在Flutter桌面应用中嵌入一个Web视图。

首先,确保你已经在你的pubspec.yaml文件中添加了desktop_webview_window依赖项:

dependencies:
  flutter:
    sdk: flutter
  desktop_webview_window: ^0.0.x  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖项。

接下来,你可以在你的Flutter应用中创建一个包含Web视图的窗口。以下是一个完整的示例代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Desktop Webview Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: _launchWebview,
            child: Text('Launch Webview'),
          ),
        ),
      ),
    );
  }

  void _launchWebview() async {
    // 配置Web视图的参数
    final webviewParams = WebviewWindowParams(
      url: 'https://www.example.com',  // 要加载的URL
      width: 1200,
      height: 800,
      title: 'Example Webview',
      resizable: true,  // 是否允许调整窗口大小
      alwaysOnTop: false,  // 是否始终位于其他窗口之上
      fullscreen: false,  // 是否全屏显示
      webPreferences: WebPreferences(
        // 配置Web视图的偏好设置,例如是否启用JavaScript
        javaScriptEnabled: true,
      ),
    );

    // 打开Web视图窗口
    final webviewWindow = await WebviewWindow.create(webviewParams);

    // 监听窗口关闭事件
    webviewWindow.onClosed.listen((_) {
      print('Webview window closed');
    });
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮。点击按钮时,会调用_launchWebview函数,该函数使用desktop_webview_window插件打开一个新的Web视图窗口,并加载指定的URL(在这个例子中是https://www.example.com)。

你可以根据需要调整WebviewWindowParams中的参数,例如窗口大小、标题、是否可调整大小、是否始终位于其他窗口之上、是否全屏显示等。WebPreferences允许你进一步配置Web视图的偏好设置,例如是否启用JavaScript。

请注意,由于Flutter和插件的不断发展,API可能会有所变化。因此,建议查阅最新的desktop_webview_window文档以获取最准确的信息。

回到顶部