SwiftUI开发macOS APP,如何自定义标题栏(TitleBar)

原创 吴就业 109 0 2024-07-28

本文为博主原创文章,未经博主允许不得转载。

本文链接:https://wujiuye.com/article/8668961e9dad47ec8b0f780908a9c8ac

作者:吴就业
链接:https://wujiuye.com/article/8668961e9dad47ec8b0f780908a9c8ac
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。

macOS APP应用的标题栏(TitleBar)是指包含“交通信号灯”(红黄绿三个小按钮)的一栏,通常TitleBar只包括“交通信号灯”和一个title。

由于我们开发的app样式不是使用的系统样式,系统提供的TitleBar我们又改不了颜色,会与我们的应用主题形成鲜明的反差,如图:

截屏2024-07-28 18.14.43

另外,TitleBar的位置我们想自由的放置一些自定义按钮、选项,不想浪费这个位置,所以我们想把TitleBar隐藏掉。

我们使用SwiftUI开发macOS APP,那么怎么把TitleBar隐藏掉呢?

答案是通过WindowGroup的windowStyle API设置窗口样式为HiddenTitleBarWindowStyle,例如:

var body: some Scene {
        WindowGroup {
            ConsoleHome(openFile: self.openFile)
        }.commands {
            //.......
        }.windowStyle(HiddenTitleBarWindowStyle())

        WindowGroup(id: "analysis") {
            ConsoleAnalysis(openFile: self.openFile)
        }.windowStyle(HiddenTitleBarWindowStyle())
    }

但,这样只是将TitleBar隐藏了而已,TitleBar占用的位置还是空在那里的。

假如我们自定义的TitleBar如下:

var body: some View {
        VStack(spacing: 0, content: {
          	// 自定义TitleBar
						HStack(spacing: 0, content: {
                Text(getTitle())
                    .font(.headline)
                    .padding(.leading, 80)
            }).frame(maxWidth: .infinity,maxHeight: 30, alignment: .leading)
                .background(.themeBackgroundBase200)
                .foregroundStyle(.themeContentBase)
          // 窗口主视图
          // ......
       })
}

现在我们只需调用一个方法,就能让自定义的TitleBar占用原先TitleBar的位置:

var body: some View {
        VStack(spacing: 0, content: {
						HStack(spacing: 0, content: {
                Text(getTitle())
                    .font(.headline)
                    .padding(.leading, 80)
            }).frame(maxWidth: .infinity,maxHeight: 30, alignment: .leading)
                .background(.themeBackgroundBase200)
                .foregroundStyle(.themeContentBase)
          // .....
       }).edgesIgnoringSafeArea(.top)
}

是的,就是调用.edgesIgnoringSafeArea(.top),让视图忽略屏幕顶部的安全区域。

设置之前:

截屏2024-07-28 18.24.35

设置之后:

截屏2024-07-28 18.24.55

最后,由于设置HiddenTitleBarWindowStyle样式之后,双击TitleBar的位置缩放窗口就不生效了,我们需要自己实现这个功能。当用户双击TitleBar时,调用NSApp.keyWindow?.zoom(nil)实现缩放窗口。

var body: some View {
        VStack(spacing: 0, content: {
						HStack(spacing: 0, content: {
                Text(getTitle())
                    .font(.headline)
                    .padding(.leading, 80)
            }).frame(maxWidth: .infinity,maxHeight: 30, alignment: .leading)
                .background(.themeBackgroundBase200)
                .foregroundStyle(.themeContentBase)
          			.onTapGesture(count: 2, perform: {
                    NSApp.keyWindow?.zoom(nil)
                })
          // .....
       }).edgesIgnoringSafeArea(.top)
}

总结:

  1. 通过WindowGroup的windowStyle API设置窗口样式为HiddenTitleBarWindowStyle,隐藏系统的默认TitleBar。
  2. 通过edgesIgnoringSafeArea(.top)来让自定义的TitleBar占用系统默认TitleBar的位置。
  3. 通过onTapGesture和NSApp.keyWindow.zoom实现双击缩放窗口的功能。
#前端

声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。

文章推荐

SwiftUI如何阻止应用进程重启恢复到之前的状态

假如你不希望你的应用重启时,恢复到上次用户打开的窗口,而是想每次都从启动页开始。那么怎么做呢?

SwiftUI原生Chart组件如何实现鼠标移动选中才显示数值

使用SwiftUI的原生Chart组件,堆叠柱形图如何实现像网站使用ercharts实现的鼠标移动到柱状图上面才弹窗显示对应数值的效果。

微信小程序原生开发获取input光标位置和监听光标位置改变问题

input失去焦点后,用户点击input重新获取焦点,怎么获取光标位置?如果用户获取到焦点之后,没有输入,而是移动光标,怎么获取移动后的光标位置呢?

如何将macOS app发布到app store?

开发完一个macOS app之后,我们应该如何将其发布到app store呢?这个文档记录了笔者从零开始一步步学习将自己开发好的macOS app发布到app store的过程。

如何编译构建一个同时支持多cpu架构的静态链接库(.a文件)

我想要让自己的mac OS应用支持更多用户可以使用,就必须要打出一个能同在amd64架构cpu的mac os设备上运行,也需要能在arm64架构cpu的mac os设备上运行。

使用node:alpine基础镜像今天突然就构建不了了

我的一个nextjs项目使用node:alpine基础镜像,在此之前部署到线上都能正常构建和运行,今天修改点代码提交到生产环境,发现竟然镜像构建失败了。