macos_window_utils 是一个 Flutter 包,提供了一套用于修改 macOS 上 Flutter 应用程序的 NSWindow 的方法。使用此包,您可以轻松自定义应用程序窗口的外观和行为,包括标题栏、透明效果、阴影等。

功能

macos_window_utils 提供以下功能(但不限于):

  • 设置应用程序窗口材质的方法。
  • 进入/退出全屏模式或(取消)缩放窗口的方法。
  • 标记窗口为“已编辑文档”的方法。
  • 设置窗口的表示文件名和 URL 的方法。
  • 隐藏/显示窗口标题的方法。
  • 启用/禁用全尺寸内容视图的方法。
  • 显示/隐藏和启用/禁用窗口交通灯按钮的方法。
  • 设置窗口 alpha 值的方法。
  • 向窗口添加工具栏并设置其样式的方法。
  • 向窗口添加副标题的方法。
  • 使窗口忽略鼠标事件的方法。
  • 使窗口完全透明(无模糊效果)的方法。
  • 启用/禁用窗口阴影的方法。
  • 添加、删除和修改视觉效果子视图的方法和组件。

此外,该包还附带一个示例项目,通过直观的可搜索用户界面展示了插件的功能。

screenshot of example project

入门

使用 Xcode 打开您项目的 macos/Runner.xcworkspace 文件夹,按 ⇧ + ⌘ + O 并搜索 MainFlutterWindow.swift

在文件顶部插入 import macos_window_utils。然后,将 super.awakeFromNib() 行以上的代码替换为以下代码:

let windowFrame = self.frame
let macOSWindowUtilsViewController = MacOSWindowUtilsViewController()
self.contentViewController = macOSWindowUtilsViewController
self.setFrame(windowFrame, display: true)

/* Initialize the macos_window_utils plugin */
MainFlutterWindowManipulator.start(mainFlutterWindow: self)

RegisterGeneratedPlugins(registry: macOSWindowUtilsViewController.flutterViewController)

假设您从默认配置开始,最终代码应如下所示:

import Cocoa
import FlutterMacOS
+import macos_window_utils

class MainFlutterWindow: NSWindow {
  override func awakeFromNib() {
-   let flutterViewController = FlutterViewController.init()
-   let windowFrame = self.frame
-   self.contentViewController = flutterViewController
-   self.setFrame(windowFrame, display: true)

-   RegisterGeneratedPlugins(registry: flutterViewController)
    
+   let windowFrame = self.frame
+   let macOSWindowUtilsViewController = MacOSWindowUtilsViewController()
+   self.contentViewController = macOSWindowUtilsViewController
+   self.setFrame(windowFrame, display: true)

+   /* Initialize the macos_window_utils plugin */
+   MainFlutterWindowManipulator.start(mainFlutterWindow: self)

+   RegisterGeneratedPlugins(registry: macOSWindowUtilsViewController.flutterViewController)

    super.awakeFromNib()
  }
}

现在再次按 ⇧ + ⌘ + O 并搜索 Runner.xcodeproj。转到 info > Deployment Target,然后将 macOS Deployment Target 设置为 10.13 或更高版本。

根据您的用例,您可能希望将 Flutter 可以绘制的窗口区域扩展到整个窗口,以便您可以在窗口的标题栏上进行绘制(例如,当您只想使侧边栏透明,而窗口的其余部分保持不透明时)。

要实现此目的,请使用以下 Dart 代码启用全尺寸内容视图:

WindowManipulator.makeTitlebarTransparent();
WindowManipulator.enableFullSizeContentView();

当您决定这样做时,建议将您的应用程序(或其部分)包装在 TitlebarSafeArea 小部件中,如下所示:

TitlebarSafeArea(
  child: YourApp(),
)

这可以确保您的应用不会被窗口的标题栏覆盖。

此外,考虑将侧边栏和主视图分成多个 NSVisualEffectView 在应用程序中。这是因为 macOS 有一项称为“壁纸着色”的功能,该功能默认启用。此功能允许窗口与桌面壁纸融为一体。

macos_wallpaper_tinting

要为您的 Flutter 应用程序实现相同的效果,您可以将窗口的材质设置为 NSVisualEffectViewMaterial.windowBackground,然后像这样将您的侧边栏小部件包装在 TransparentMacOSSidebar 小部件中:

TransparentMacOSSidebar(
  child: YourSidebarWidget(),
)

注意: 当检测到小部件 build 方法中的窗口大小调整时,该小部件将自动调整 NSVisualEffectView 的大小。如果您使用 TweenAnimationBuilder 为侧边栏的大小设置动画,请确保 TransparentMacOSSidebar 小部件在 TweenAnimationBuilderbuild 方法中构建,以保证在大小更改时触发重建。作为参考,在 example 项目的 transparent_sidebar_and_content.dart 文件中有一个工作示例。

用法

按如下方式初始化插件:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await WindowManipulator.initialize();
  runApp(MyApp());
}

之后,调用 WindowManipulator 类中的任何方法来操作您的应用程序窗口。

许可证

MIT 许可

GitHub

查看 Github