使用 SegmentedPickerStyle 为 SwiftUI Picker 设置段宽度相等
Set segment equal width for SwiftUI Picker with SegmentedPickerStyle
使用 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())
这是默认的 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 !!
[=11=].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) {
}
}
啊,深入到 AppKit 方法。
确实很聪明。
然而,这对我不起作用,Monteray 12.3
使用 Xcode 的可视化调试器进一步调试,我可以在视图层次结构中看到 NSPickerConfigurator class,但没有 NSSegmetedControl。
看起来苹果正在从层次结构中清除 NSViews。
是时候考虑纯粹的 swiftui 了。
...For examle, the picker in the image has a different width for text.
如果您来到这里寻求 iOS SwiftUI SegmentedPickerStyle 解决方案...我发现 iOS SwiftUI .pickerStyle(SegmentedPickerStyle())
将符合全局 UISegmentedControl.appearance()
设置,所以我使用以下方法成功分配每个段的宽度:
UISegmentedControl.appearance().apportionsSegmentWidthsByContent = true
例如,如果您想在您的应用中支持动态类型字体,这将特别有用,否则可能会导致名称较长的段爆裂并被截断。 [旁白:我还使用这个技巧来更改 SwiftUI 分段选择器的字体大小!参见
使用 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())
这是默认的 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 !!
[=11=].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) {
}
}
啊,深入到 AppKit 方法。
确实很聪明。 然而,这对我不起作用,Monteray 12.3
使用 Xcode 的可视化调试器进一步调试,我可以在视图层次结构中看到 NSPickerConfigurator class,但没有 NSSegmetedControl。
看起来苹果正在从层次结构中清除 NSViews。
是时候考虑纯粹的 swiftui 了。
...For examle, the picker in the image has a different width for text.
如果您来到这里寻求 iOS SwiftUI SegmentedPickerStyle 解决方案...我发现 iOS SwiftUI .pickerStyle(SegmentedPickerStyle())
将符合全局 UISegmentedControl.appearance()
设置,所以我使用以下方法成功分配每个段的宽度:
UISegmentedControl.appearance().apportionsSegmentWidthsByContent = true
例如,如果您想在您的应用中支持动态类型字体,这将特别有用,否则可能会导致名称较长的段爆裂并被截断。 [旁白:我还使用这个技巧来更改 SwiftUI 分段选择器的字体大小!参见