English | 简体中文
macos_window_utils 是一个 Flutter 包,它提供了一组方法来修改 macOS 上 Flutter 应用程序的 NSWindow。使用此包,您可以轻松自定义应用程序窗口的外观和行为,包括标题栏、透明效果、阴影等。
macos_window_utils 提供了以下功能:
- 设置应用程序窗口材质。
- 进入/退出全屏模式或(取消)缩放窗口。
- 将一个窗口标记为“文档已编辑”。
- 设置代表的文件名和 URL。
- 隐藏/显示窗口的标题。
- 启用/禁用全尺寸内容视图。
- 显示/隐藏和启用/禁用窗口的交通灯按钮(就左上角三个按钮)。
- 设置窗口的透明度。
- 添加工具栏到窗口并设置其样式。
- 为窗口添加副标题。
- 使窗口忽略鼠标事件。
- 使窗口完全透明(没有模糊效果)。
- 启用/禁用窗口的阴影。
- 添加、删除和修改视觉效果子视图的方法和小部件。
- 设置窗口的级别以及在其级别内重新排序窗口。
- 修改窗口样式遮罩(style mask)。
- 一个抽象的
NSWindowDelegate类,可用于检测NSWindow事件,例如窗口调整大小、移动、暴露和最小化。 - 一个
NSAppPresentationOptions类,允许修改窗口的全屏演示选项。 - 获取和设置窗口标准窗口按钮(例如关闭、缩小和缩放按钮)位置的方法。
- 控制窗口是否应关闭用户以及以编程方式关闭窗口的方法。
此外,该包还附带了一个示例项目,通过直观的可搜索用户界面展示了插件的功能:
首先,通过以下命令安装包:
flutter pub add macos_window_utils
然后,使用 Xcode 打开项目的 macos/Runner.xcworkspace 文件夹,按 ⇧ + ⌘ + O 并搜索 Runner.xcodeproj。
前往 Info > Deployment Target 并将 macOS Deployment Target 设置为 10.14.6 或更高。然后,打开项目的 Podfile(如果它没有在 Xcode 中显示,您可以通过 VS Code 在项目的 macos 目录中找到它)并将在第一行的最小部署版本设置为 10.14.6 或更高:
platform :osx, '10.14.6'根据你的需求,您可能希望将 Flutter 可以绘制的窗口区域扩展到整个窗口,这样您就可以在窗口的标题栏上绘制(例如,当您只想让侧边栏透明,而窗口的其他部分保持不透明时)。
为此,请使用以下 Dart 代码启用全尺寸内容视图:
WindowManipulator.makeTitlebarTransparent();
WindowManipulator.enableFullSizeContentView();当决定这样做时,建议将应用程序(或其部分)包装在 TitlebarSafeArea 小部件中,如下所示:
TitlebarSafeArea(
child: YourApp(),
)这样可以确保您的应用程序不会被窗口的标题栏覆盖。
此外,您可能应该考虑在应用程序中将侧边栏和主视图拆分为多个 NSVisualEffectView。这是因为 macOS 有一个名为 “wallpaper tinting” 的功能,处于默认启动的状态。此功能允许窗口与桌面壁纸融合(blend):
要在 Flutter 应用程序中实现相同的效果,您可以将窗口的材质设置为 NSVisualEffectViewMaterial.windowBackground,并使用 TransparentMacOSSidebar 小部件包装侧边栏小部件,如下所示:
TransparentMacOSSidebar(
child: YourSidebarWidget(),
)注意:当检测到在一个部件的 build 方法中检测到调整大小时,该部件将自动调整 NSVisualEffectView 的大小。如果您正在使用 TweenAnimationBuilder 以动画的方式调整侧边栏的大小,请确保 TransparentMacOSSidebar 小部件在 TweenAnimationBuilder 的 build 方法中构建,以确保在大小更改时触发重建。可以参考在 example 中 transparent_sidebar_and_content.dart 的示例。
如下所示初始化插件:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await WindowManipulator.initialize();
runApp(MyApp());
}然后,调用 WindowManipulator 类的任何方法来操作您的应用程序窗口。
NSWindowDelegate 可用于监听 NSWindow 事件,例如窗口调整大小、移动、暴露和最小化。为了使用它,请首先确保在您的 WindowManipulator.initialize 调用中将 enableWindowDelegate 设置为 true:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// 默认情况下,enableWindowDelegate 设置为 false,以确保与其他插件兼容。如果您希望使用 NSWindowDelegate,请将其设置为 true。
await WindowManipulator.initialize(enableWindowDelegate: true);
runApp(MyApp());
}然后,创建一个扩展它的类:
class _MyDelegate extends NSWindowDelegate {
@override
void windowDidEnterFullScreen() {
print('已进入全屏模式');
super.windowDidEnterFullScreen();
}
}此类重写 NSWindowDelegate 的 windowDidEnterFullScreen 方法以响应它。
以下方法目前由 NSWindowDelegate 支持:
支持的方法
- 管理 Sheets
windowWillBeginSheetwindowDidEndSheet
- 调整窗口大小
windowWillResizewindowDidResizewindowWillStartLiveResizewindowDidEndLiveResize
- 最小化窗口
windowWillMiniaturizewindowDidMiniaturizewindowDidDeminiaturize
- 缩放窗口
windowWillUseStandardFramewindowShouldZoom
- 管理全屏展示
windowWillEnterFullScreenwindowDidEnterFullScreenwindowWillExitFullScreenwindowDidExitFullScreen
- 移动窗口
windowWillMovewindowDidMovewindowDidChangeScreenwindowDidChangeScreenProfilewindowDidChangeBackingProperties
- 关闭窗口
windowShouldClosewindowWillClose
- 管理 Key 状态(Managing Key Status)
windowDidBecomeKeywindowDidResignKey
- 管理主要状态
windowDidBecomeMainwindowDidResignMain
- 暴露窗口
windowDidExpose
- 管理遮挡状态
windowDidChangeOcclusionState
- 管理版本浏览器中的演示( Managing Presentation in Version Browsers )
windowWillEnterVersionBrowserwindowDidEnterVersionBrowserwindowWillExitVersionBrowserwindowDidExitVersionBrowser
然后,通过 WindowManipulator.addNSWindowDelegate 方法添加一个实例:
final delegate = _MyDelegate();
final handle = WindowManipulator.addNSWindowDelegate(delegate);WindowManipulator.addNSWindowDelegate 返回一个 NSWindowDelegateHandle,它可以用来稍后再次删除此 NSWindowDelegate:
handle.removeFromHandler();假设我们希望在窗口处于全屏模式时自动隐藏工具栏。使用 NSAppPresentationOptions 可以按如下方式完成:
// 创建 NSAppPresentationOptions 实例。
final options = NSAppPresentationOptions.from({
// fullScreen 需要始终作为全屏选项存在。
NSAppPresentationOption.fullScreen,
// 在全屏模式下自动隐藏工具栏。
NSAppPresentationOption.autoHideToolbar,
// autoHideToolbar 必须与 autoHideMenuBar 一起使用。
NSAppPresentationOption.autoHideMenuBar,
// autoHideMenuBar 必须与 autoHideDock 或 hideDock 之一 一起使用。
NSAppPresentationOption.autoHideDock,
});
// 将选项应用为全屏选项。
options.applyAsFullScreenPresentationOptions();注意:NSAppPresentationOptions 使用 NSWindow 的委托来更改窗口的全屏选项。因此,enableWindowDelegate 需要在您的 WindowManipulator.initialize 调用中设置为 true 才能正常工作。
MIT License

