使用SegmentedPickerStyle为SwiftUI Picker设置段相等的宽度

时间:2020-05-16 06:52:25

标签: swift macos swiftui picker

使用SegmentedPickerStyle样式Picker可以使控件看起来像UISegmentedControl。但是我不知道如何在选择器中调整段宽度。例如,图像中的选择器具有不同的文本宽度。

在SwiftUI中是否可以使片段的宽度相同?

    Picker(selection: $store.utility.saliencyType, label: EmptyView()) {
        ForEach(Store.Utility.SaliencyType.allCases, id: \.self) { saliencyType in
            Text(saliencyType.text)
                .tag(saliencyType)
        }
    }.pickerStyle(SegmentedPickerStyle())

enter image description here

1 个答案:

答案 0 :(得分:1)

这是默认的macOS NSSegmetedControl行为

@property NSSegmentDistribution segmentDistribution API_AVAILABLE(macos(10.13)); 
// Defaults to NSSegmentDistributionFill on 10.13, older systems will continue to behave similarly to NSSegmentDistributionFit

更新:以下是变通办法,它基于在运行时视图层次结构中找到NSSegmentedControl

demo

免责声明:实际上,这是安全的,即。在运行时不会崩溃,但是将来可以恢复默认行为就可以停止工作。

因此,我们的想法是通过可表示形式将NSView注入(!!)Picker上方的视图层次结构中,如

Picker(selection: $store.utility.saliencyType, label: EmptyView()) {
        ForEach(Store.Utility.SaliencyType.allCases, id: \.self) { saliencyType in
            Text(saliencyType.text)
                .tag(saliencyType)
        }
    }
    .overlay(NSPickerConfigurator {                // << here !!
        $0.segmentDistribution = .fillEqually // change style !!
    })
    .pickerStyle(SegmentedPickerStyle())

和配置器本身

struct NSPickerConfigurator: NSViewRepresentable {
    var configure: (NSSegmentedControl) -> Void

    func makeNSView(context: Context) -> NSView {
        let view = NSView()
        DispatchQueue.main.async {
            if let holder = view.superview?.superview {
                let subviews = holder.subviews
                if let nsSegmented = subviews.first?.subviews.first as? NSSegmentedControl {
                    self.configure(nsSegmented)
                }
            }
        }
        return view
    }

    func updateNSView(_ nsView: NSView, context: Context) {
    }
}