如何在 SwiftUI for macOS 中创建首选项样式工具栏?

How do you create a Preferences Style toolbar in SwiftUI for macOS?

我正在尝试为 macOS 上的 SwiftUI 设置视图创建首选项样式工具栏(文本图标)。使用以下代码:

struct PreferencesView: View {
    
    //MARK: Constants and Variables
    
    @AppStorage("authToken") var authToken: String = ""
    @AppStorage("author") var author: String = ""

    
    //MARK: Main
    var body: some View {
        VStack {
            HStack {
                VStack (alignment: .leading, spacing: 10) {
                    Text("Author:")
                    Text("GitHub Auth Token:")
                }
                VStack {
                    TextField("", text: $author)
                    TextField("", text: $authToken)
                }
            }
            .padding()
            
            Spacer()
        }

        .toolbar {
            ToolbarItem(placement: .principal) {
                Button {
                } label: {
                    Label {
                        Text("General")
                    } icon: {
                        Image (systemName: "gearshape")
                    }
                    .labelStyle (VerticalLabelStyle()) //custom label style
                }
            }
        }
        .frame(width: 480, height: 320)
    }
}

结果是一个只显示底部的按钮。

标签样式定义如下:

struct VerticalLabelStyle: LabelStyle {

    @ViewBuilder
    func makeBody(configuration: Configuration) -> some View {
        VStack {
            configuration.icon
                .font(.largeTitle)
            configuration.title
        }
    }
}

有人知道如何在 macOS 上的 SwiftUI 中成功创建它吗?

这里有一个适合你的方法:

struct ContentView: View {
    
    @AppStorage("authToken") var authToken: String = ""
    @AppStorage("author") var author: String = ""

    var body: some View {
        VStack {
            HStack {
                VStack (alignment: .leading, spacing: 10) {
                    Text("Author:")
                    Text("GitHub Auth Token:")
                }
                VStack {
                    TextField("", text: $author)
                    TextField("", text: $authToken)
                }
            }
            .padding()
            
            Spacer()
        }
        .toolbar(content: {
            
            ToolbarItem(placement: .principal) {

                HStack {
                    
                    ToolbarItemView(string: "General", imageSystemName: "gearshape", action: actionOfGeneral)
                    
                    ToolbarItemView(string: "About", imageSystemName: "info.circle", action: actionOfAbout)
                }
 
            }
            
        })
        .frame(width: 480, height: 320)
    }
    
    private func actionOfGeneral() { print("General clicked!") }
    private func actionOfAbout() { print("About clicked!") }

}


struct ToolbarItemView: View {
    
    let string: String
    let imageSystemName: String
    let action: () -> Void
    
    @State private var isPressing: Bool = Bool()
    var body: some View {
        
        VStack(spacing: 2.0) {
            Image(systemName: imageSystemName)
            Text(string)
        }
        .frame(width: 50)
        .background(Color.white.opacity(0.01))
        .padding(.horizontal, 5.0)
        .padding(.vertical, 2.0)
        .overlay(RoundedRectangle(cornerRadius: 5.0).stroke(Color.secondary.opacity(0.5), style: StrokeStyle(lineWidth: 1.0)))
        .opacity(isPressing ? 0.75 : 1.0)
        .scaleEffect(isPressing ? 0.95 : 1.0)
        .gesture(DragGesture(minimumDistance: .zero, coordinateSpace: .local).onChanged { _ in isPressing = true }.onEnded { _ in isPressing = false; action() })
        .animation(Animation.interactiveSpring(), value: isPressing)
        
    }
    
}

您在使用 SwiftUI 应用程序生命周期吗?如果是这样,请将 TabView 添加到您的 Settings 视图,然后选项卡将自动出现在工具栏中:

Settings {
    TabView {
        PreferencesView()
            .tabItem {
                Label("General", systemImage: "gearshape")
            }
    }
}

如果您不使用 SwiftUI 应用程序生命周期,那么我认为您需要使用 NSToolbar 手动构建这种风格的工具栏。

我发现 Apple 推荐的方法是放入 TabView。效果很好。

var body: some View {
        TabView {
            GeneralSettingsView
                .tabItem {
                    Label("General", systemImage: "gearshape")
                }
        }
    }