首页 > 解决方案 > 使用 SegmentedPickerStyle 为 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())

在此处输入图像描述

标签: swiftmacosswiftuipicker

解决方案


这是默认的 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在运行时视图层次结构中查找的解决方法。

演示

免责声明:实际上它是安全的,即。运行时没有崩溃,但可以在将来返回默认行为时停止工作。

因此,想法是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) {
    }
}

推荐阅读