SwiftUI中HStack内应用WheelPickerStyle的Picker如何调整大小避免响应错位
解决方案
根因说明
WheelPickerStyle 对应的原生滚轮控件默认的手势响应区域不会跟随你设置的 frame 自动裁剪,你添加的 .clipped() 只会裁剪视觉可见的内容,不会修改手势触发的热区范围,多个Picker的热区重叠后就会出现点击左侧控件实际响应右侧控件的异常。
修复方法
给每个 Picker 的 .clipped() 修饰符后,新增 .contentShape(Rectangle()) 修饰符,主动将手势响应范围限制为当前Picker的可见frame区域即可。
额外优化建议
- 原代码中分钟、秒的数组范围设为
0...60存在逻辑错误,最多到59分/59秒,建议改为0...59 - 50pt的高度会导致滚轮选项显示不全,建议调整到100~120pt,使用体验更好
- 建议把
.pickerStyle(WheelPickerStyle())放到frame修饰符之前,符合SwiftUI修饰符的最佳实践顺序
修复后完整代码
struct DatePickerView: View { var hoursArray = [Int](0...23) var minsArray = [Int](0...59) var secondsArray = [Int](0...59) @State var hoursSelection: Int = 0 @State var minsSelection: Int = 0 @State var secsSelection: Int = 0 var body: some View { VStack { Text("Select time.").font(.headline) HStack(spacing: 0) { Picker(selection: $hoursSelection, label: Text("Hours")) { ForEach(0..<hoursArray.count) { idx in Text("\(hoursArray[idx])") } } .pickerStyle(WheelPickerStyle()) .frame(width: 50, height: 120, alignment: .center) .border(Color.red) .clipped() .contentShape(Rectangle()) Picker(selection: $minsSelection, label: Text("Minutes")) { ForEach(0..<minsArray.count) { idx in Text("\(minsArray[idx])") } } .pickerStyle(WheelPickerStyle()) .frame(width: 50, height: 120, alignment: .center) .border(Color.green) .clipped() .contentShape(Rectangle()) Picker(selection: $secsSelection, label: Text("Seconds")) { ForEach(0..<secondsArray.count) { idx in Text("\(secondsArray[idx])") } } .pickerStyle(WheelPickerStyle()) .frame(width: 50, height: 120, alignment: .center) .border(Color.blue) .clipped() .contentShape(Rectangle()) } } } }
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

