You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SwiftUI的MenuBarExtra中实现带边框的特定Form样式?

SwiftUI MenuBarExtra 中 Form 边框不显示问题解决

我在SwiftUI的MenuBarExtra(窗口样式)里实现Form时,遇到了样式问题:期望表单带有边框,但实际显示的Form没有边框。以下是我最初的代码:

struct MyApp: App {
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        
        MenuBarExtra("Internet Service", systemImage: "network") {
            InternetInfo()
        }
        .menuBarExtraStyle(.window)

    }
}

struct InternetInfo: View {
    @State var usage: Double = 230.0
    @State var quota: Double = 60.0

    var body: some View {
        Form {
            
            Gauge(value: usage, in: 0...1000) {
                Text("Used Bandwidth")
            } currentValueLabel: {
                Text("\(Int(usage)) GB").font(.caption)
            }
            
            Gauge(value: quota, in: 0...100) {
                Text("Disk Quota")
            } currentValueLabel: {
                Text("\(Int(quota)) GB").font(.caption)
            }
            
        }
        .gaugeStyle(.accessoryLinearCapacity)
        .formStyle(.grouped)
    }
}

问题原因

在macOS的MenuBarExtra窗口中,.formStyle(.grouped)不会像常规WindowGroup里那样自动添加边框——这是因为MenuBarExtra的窗口容器样式和普通窗口不同,系统默认不会给这里的Form加上边框装饰。

解决方法

方法1:直接给Form添加自定义边框

最简单的方式是给Form加上border修饰符,配合padding调整间距,快速模拟预期效果:

struct InternetInfo: View {
    @State var usage: Double = 230.0
    @State var quota: Double = 60.0

    var body: some View {
        Form {
            Gauge(value: usage, in: 0...1000) {
                Text("已用带宽")
            } currentValueLabel: {
                Text("\(Int(usage)) GB").font(.caption)
            }
            
            Gauge(value: quota, in: 0...100) {
                Text("磁盘配额")
            } currentValueLabel: {
                Text("\(Int(quota)) GB").font(.caption)
            }
        }
        .gaugeStyle(.accessoryLinearCapacity)
        .formStyle(.grouped)
        .border(Color(.separator), width: 1) // 添加系统分隔线颜色的边框
        .padding(8) // 边框与Form之间留间距
        .frame(width: 300, height: 180) // 可选:固定窗口尺寸,布局更整齐
    }
}

方法2:使用原生NSTextField边框(更贴近系统样式)

如果想要完全匹配macOS原生的边框视觉效果,可以封装一个NSViewRepresentable的容器:

// 封装带边框的原生容器
struct BorderedContainer: NSViewRepresentable {
    func makeNSView(context: Context) -> NSTextField {
        let field = NSTextField()
        field.isBordered = true
        field.isEditable = false
        field.drawsBackground = true
        field.backgroundColor = .textBackgroundColor
        return field
    }
    
    func updateNSView(_ nsView: NSTextField, context: Context) {}
}

// 修改后的InternetInfo视图
struct InternetInfo: View {
    @State var usage: Double = 230.0
    @State var quota: Double = 60.0

    var body: some View {
        BorderedContainer()
            .padding(8)
            .overlay(
                Form {
                    Gauge(value: usage, in: 0...1000) {
                        Text("已用带宽")
                    } currentValueLabel: {
                        Text("\(Int(usage)) GB").font(.caption)
                    }
                    
                    Gauge(value: quota, in: 0...100) {
                        Text("磁盘配额")
                    } currentValueLabel: {
                        Text("\(Int(quota)) GB").font(.caption)
                    }
                }
                .gaugeStyle(.accessoryLinearCapacity)
                .formStyle(.grouped)
                .padding(8)
            )
            .frame(width: 300, height: 180)
    }
}

第一种方法适合快速实现需求,第二种方法能获得更贴合系统的原生视觉体验,可以根据自己的需求选择。

内容的提问来源于stack exchange,提问作者MohAliBou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:22:51