如何让SwiftUI分段Picker的宽度适配自身内容而非最宽分段?
SwiftUI分段Picker如何让各分段宽度适配自身内容?
默认使用.segmented样式的Picker会让所有分段统一适配最长选项的宽度,导致短内容的分段被不必要地拉长。比如以下代码:
func segments() -> [String] { var toReturn = Calendar.current.veryShortWeekdaySymbols toReturn.append("T") return toReturn } Picker("Day of week?", selection: $selectedDay) { ForEach(segments(), id: \.self) { Text($0) .scaledToFit() } } .pickerStyle(.segmented) .fixedSize()
此时显示效果正常,各分段宽度适配自身内容:
但如果将toReturn.append("T")改为添加更长的字符串toReturn.append("Tasks"),所有分段都会被拉宽以适配最长的"Tasks"选项:
解决方案:自定义分段选择器
原生.segmented样式不支持分段独立适配内容宽度,我们可以用HStack+Button模拟分段选择器,让每个分段根据自身内容调整宽度,同时实现选中状态的样式。
基础实现代码
@State private var selectedDay: String = "" func segments() -> [String] { var toReturn = Calendar.current.veryShortWeekdaySymbols toReturn.append("Tasks") return toReturn } var body: some View { HStack(spacing: 0) { ForEach(segments(), id: \.self) { item in Button(action: { selectedDay = item }) { Text(item) .padding(.horizontal, 12) .padding(.vertical, 8) .background(selectedDay == item ? Color.blue : Color.gray.opacity(0.2)) .foregroundColor(selectedDay == item ? .white : .primary) .cornerRadius(6) } .buttonStyle(.plain) } } .fixedSize() }
贴近原生样式的优化版
如果需要和原生分段Picker一样的两端圆角、中间无圆角效果,可以通过蒙版调整圆角:
HStack(spacing: 0) { ForEach(Array(segments().enumerated()), id: \.element) { index, item in Button(action: { selectedDay = item }) { Text(item) .padding(.horizontal, 12) .padding(.vertical, 8) .background( RoundedRectangle(cornerRadius: 6) .fill(selectedDay == item ? Color.blue : Color.gray.opacity(0.2)) .mask({ HStack { if index == 0 { Rectangle() .cornerRadius(6, corners: [.topLeft, .bottomLeft]) } else if index == segments().count - 1 { Rectangle() .cornerRadius(6, corners: [.topRight, .bottomRight]) } else { Rectangle() } } }) ) .foregroundColor(selectedDay == item ? .white : .primary) } .buttonStyle(.plain) } } .fixedSize()
这种自定义方案不仅能让每个分段宽度适配自身内容,还能自由调整选中/未选中的样式、内边距等,比原生Picker更灵活。
内容的提问来源于stack exchange,提问作者sudoExclamationExclamation
相关产品推荐
相关产品推荐

