如何在Flutter Windows桌面应用中实现全屏切换功能?
Flutter Windows 实现全屏/窗口模式切换(无顶栏底栏)
下面提供两种可行方案,实现类似Chrome F11的全屏切换效果,支持通过图标、弹窗等触发。
方案一:使用 window_manager 第三方包(简单快捷)
这个包封装了Windows窗口操作的常用API,无需自己编写原生代码。
- 添加依赖
在pubspec.yaml中加入:
dependencies: window_manager: ^0.3.0
执行flutter pub get完成安装。
- 初始化窗口管理
修改main.dart的main函数,初始化window_manager:
import 'package:flutter/material.dart'; import 'package:window_manager/window_manager.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await windowManager.ensureInitialized(); // 初始窗口配置 const windowOptions = WindowOptions( title: "全屏切换Demo", size: Size(800, 600), center: true, ); windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.show(); await windowManager.focus(); }); runApp(const MyApp()); }
- 实现切换逻辑
在页面的State类中添加状态变量和切换方法:
bool _isFullScreen = false; Future<void> _toggleFullScreen() async { _isFullScreen = !_isFullScreen; if (_isFullScreen) { // 进入全屏:隐藏标题栏、边框,覆盖整个屏幕 await windowManager.setFullScreen(true); // 可选:隐藏任务栏中的窗口图标 await windowManager.setSkipTaskbar(true); } else { // 退出全屏:恢复原窗口状态 await windowManager.setFullScreen(false); await windowManager.setSkipTaskbar(false); // 恢复初始窗口大小(可按需调整) await windowManager.setSize(const Size(800, 600)); await windowManager.center(); } setState(() {}); }
- 添加触发入口
- 图标按钮触发:
AppBar( title: const Text("全屏切换Demo"), actions: [ IconButton( icon: Icon(_isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen), onPressed: _toggleFullScreen, ), ], )
- 弹窗触发:
TextButton( onPressed: () { showDialog( context: context, builder: (context) => AlertDialog( title: const Text("切换全屏模式"), content: const Text("确认进入全屏?"), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text("取消"), ), TextButton( onPressed: () { Navigator.pop(context); _toggleFullScreen(); }, child: const Text("确认"), ), ], ), ); }, child: const Text("打开全屏切换弹窗"), )
- Windows平台额外配置
打开windows/runner/main.cpp,添加一行代码绑定窗口句柄:
// ... 原有代码 ... FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(800, 600); if (!window.CreateAndShow(L"fullscreen_demo", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); // 添加这一行 window_manager::WindowManagerPlugin::SetWindow(window.GetHandle()); // ... 原有代码 ...
方案二:原生Windows API调用(无第三方依赖)
如果不想依赖第三方包,可以通过dart:ffi直接调用Windows的user32.dll实现窗口样式修改。
- 定义Win32 API绑定
创建win32_utils.dart文件,写入:
import 'dart:ffi'; import 'dart:io'; import 'package:flutter/foundation.dart'; typedef SetWindowProc = IntPtr Function(IntPtr hwnd, Int32 nIndex, IntPtr dwNewLong); typedef SetWindow = int Function(int hwnd, int nIndex, int dwNewLong); typedef GetWindowProc = IntPtr Function(IntPtr hwnd, Int32 nIndex); typedef GetWindow = int Function(int hwnd, int nIndex); class Win32 { static final DynamicLibrary user32 = Platform.isWindows ? DynamicLibrary.open('user32.dll') : throw UnsupportedError('仅支持Windows平台'); static final SetWindow setWindowLongPtr = user32 .lookupFunction<SetWindowProc, SetWindow>('SetWindowLongPtrW'); static final GetWindow getWindowLongPtr = user32 .lookupFunction<GetWindowProc, GetWindow>('GetWindowLongPtrW'); static const int GWL_STYLE = -16; static const int WS_CAPTION = 0x00C00000; // 标题栏样式 static const int WS_THICKFRAME = 0x00040000; // 可调整边框 static const int WS_MAXIMIZEBOX = 0x00010000; // 最大化按钮 static const int WS_MINIMIZEBOX = 0x00020000; // 最小化按钮 }
- 获取窗口句柄
在页面中添加获取当前窗口句柄的方法:
int getWindowHandle() { if (kIsWeb) return 0; // Flutter 3.0+ 支持的API,获取当前窗口句柄 return PlatformDispatcher.instance.views.first.windowHandle; }
- 实现切换逻辑
在页面State类中添加状态变量和切换方法:
bool _isFullScreen = false; int _originalWindowStyle = 0; Rect? _originalWindowBounds; Future<void> _toggleFullScreen() async { final hwnd = getWindowHandle(); if (hwnd == 0) return; _isFullScreen = !_isFullScreen; final windowManager = WidgetsBinding.instance.windowManager; if (_isFullScreen) { // 保存原窗口状态 _originalWindowStyle = Win32.getWindowLongPtr(hwnd, Win32.GWL_STYLE); _originalWindowBounds = await windowManager.getBounds(); // 移除标题栏、边框和最大化/最小化按钮 final newStyle = _originalWindowStyle & ~( Win32.WS_CAPTION | Win32.WS_THICKFRAME | Win32.WS_MAXIMIZEBOX | Win32.WS_MINIMIZEBOX ); Win32.setWindowLongPtr(hwnd, Win32.GWL_STYLE, newStyle); // 设置全屏尺寸(覆盖整个屏幕) final screenSize = WidgetsBinding.instance.window.physicalSize / WidgetsBinding.instance.window.devicePixelRatio; await windowManager.setBounds(Rect.fromLTWH(0, 0, screenSize.width, screenSize.height)); } else { // 恢复原窗口样式和位置大小 Win32.setWindowLongPtr(hwnd, Win32.GWL_STYLE, _originalWindowStyle); if (_originalWindowBounds != null) { await windowManager.setBounds(_originalWindowBounds!); } } setState(() {}); }
- 触发入口
和方案一完全一致,使用IconButton或AlertDialog调用_toggleFullScreen即可。
注意事项
- 方案一的
window_manager包还支持更多窗口操作(如隐藏任务栏、置顶等),可按需扩展。 - 方案二的原生API方式需要注意Flutter版本,
PlatformDispatcher.instance.views.first.windowHandle仅在Flutter 3.0及以上可用。 - 测试时需编译Windows桌面应用(
flutter run -d windows),模拟器无法完全模拟全屏效果。
内容的提问来源于stack exchange,提问作者YUNN
相关产品推荐
相关产品推荐

