MacOS 如何在SwiftUI应用的窗口标题栏中添加并图标和自定义布局

Toolbars 的文档:

https://developer.apple.com/documentation/swiftui/toolbars

首先创建一个新的MacOS APP项目,名称随喜,在本例子中我的App名称为「easyToolbar」

实现代码均在「ConternView」中编写,我简单修改了默认代码,按下运行可以看到如下的window界面

WX20240612-1147282

1,在toolbar 添加图标

「ConternView」的代码修成如下:

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!\n\nWelcome to www.lingshunlab.com")
                .multilineTextAlignment(.center) // Set text alignment to centre
        }
        .padding()
        .toolbar {
            ToolbarItem() {
                Image(systemName: "bell")
            }
        }
    }
}

运行App ,可以看到如下window的toolbar布局,元素默认是自动布局在右边

WX20240612-1201202

2,在toolbar添加按钮

「ConternView」的代码修成如下:

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!\n\nWelcome to www.lingshunlab.com")
                .multilineTextAlignment(.center) // Set text alignment to centre
        }
        .padding()
        .toolbar {
            ToolbarItem() {
                Image(systemName: "bell")
            }
            ToolbarItem() {
                Button(action: {}) {
                    Image(systemName: "gear")
                }
            }
        }
    }
}

运行App ,可以看到如下window的toolbar布局,就这么一看图标和按钮都看着一样,但是当你鼠标在按钮上经过的时候,该按钮的背景色会产生变化,并且可以在代码中添加该按钮的触发代码,进行功能上的处理。

WX20240612-1206112

3,在toolbar中添加文本输入框

「ConternView」的代码修成如下:

import SwiftUI

struct ContentView: View {
    @State private var searchText = ""

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!\n\nWelcome to www.lingshunlab.com")
                .multilineTextAlignment(.center) // Set text alignment to centre
        }
        .padding()
        .toolbar {
            ToolbarItem() {
                Image(systemName: "bell")
            }
            ToolbarItem() {
                Button(action: {}) {
                    Image(systemName: "gear")
                }
            }
            ToolbarItem {
                TextField("搜索", text: $searchText)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
            }
        }
    }
}

运行App ,可以看到如下window的toolbar布局,现在多了一个文本输入框,并且与searchText变量绑定了

WX20240612-1216592

4,把toolbar元素排在左边

使用placement:.navigation可以把toolbarItem放置在左侧,可以针对特定的toolbar元素进行布局,就可实现左右的排版方式,如下图显示:

WX20240612-1402462

navigation 文档说明

The item represents a navigation action.

https://developer.apple.com/documentation/swiftui/toolbaritemplacement/navigation

5,把toolbar元素放在中间

这次,使用placement:.principal这个可以把该元素及后面的元素都自动排列在中间,

...

ToolbarItem(placement: .principal) {
                Button(action: {}) {
                    Image(systemName: "gear")
                }
            }

...

如下图显示:

WX20240612-1455062

principal 文档说明

The system places the item in the principal item section.

https://developer.apple.com/documentation/swiftui/toolbaritemplacement/principal

6,把toolbar元素分左-中-右布局

要实现分三栏左中右布局,则要使用ToolbarItemGroup()进行布局,并且使用Spacer()这个方法自动填充,代码现修改如下:

import SwiftUI

struct ContentView: View {
    @State private var searchText = ""

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!\n\nWelcome to www.lingshunlab.com")
                .multilineTextAlignment(.center) // Set text alignment to centre
        }
        .padding()
        .toolbar {
            ToolbarItemGroup(placement: .navigation) {
                Image(systemName: "bell")
            }
            ToolbarItemGroup(placement: .principal) {
                Button(action: {}) {
                    Image(systemName: "gear")
                }
            }
            ToolbarItemGroup() {
                Spacer()
                TextField("搜索", text: $searchText)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
            }
        }
    }
}

运行App,可以看到类似的window布局:

WX20240612-1518222

7,把toolbar的标题去掉

由于无法控制window原本的标题显示的位置,所以可以通过隐藏标题,然和再在toolbar中添加标题来控制布局。

隐藏原本的标题的方法,则需要修改显示这个window的上一级的文件,例如在这里是「easyToolbarApp」,在ContentView()后添加navigationTitle("")为空则可,

修改后,运行App则可用看到如下window已经没有显示窗口标题:

WX20240612-1521472