SwiftUI自定义时间选择器如何将Picker显示行数从10行改为3行
解决方案
SwiftUI 原生的滚轮样式Picker没有公开的行数调整参数,你可以通过固定选项行高+限制Picker总高度裁剪的方式实现仅显示3行的效果,修改逻辑如下:
- 给Picker内的每个文本选项设置固定行高,你可以根据你使用的字体大小调整数值,这里以行高60为例
- 给Picker设置3倍行高的固定高度,配合
clipped()裁剪掉上下多余的内容,就能仅展示中间3行
修改后的TimePickerView核心代码
import SwiftUI struct TimePickerView: View { @ObservedObject var timeViewModel = TimePickerViewModel() var numberPressed: ((Date) -> Void)? // 可根据设计调整行高 private let pickerRowHeight: CGFloat = 60 var body: some View { GeometryReader { geo in VStack(alignment: .center) { HStack { Picker("", selection: $timeViewModel.hour) { ForEach(timeViewModel.hoursArray, id: \.self) { index in HStack { Text("\(index < 10 ? "0" : "")\(index)") .foregroundColor(.green) .font(.largeTitle) // 固定单行行高 .frame(height: pickerRowHeight) .padding() .onTapGesture { timeViewModel.changeToMinutes = false } } } } .pickerStyle(.wheel) .frame(maxWidth: geo.size.width * 0.4) // 总高度为3行高度 .frame(height: pickerRowHeight * 3) .clipped() .compositingGroup() // 可选:加渐变遮罩模拟原生Picker的上下半透明效果 .overlay { LinearGradient( colors: [.white.opacity(0.9), .clear, .white.opacity(0.9)], startPoint: .top, endPoint: .bottom ) .allowsHitTesting(false) } Text(":") .font(.largeTitle) .foregroundColor(.orange) Picker("", selection: $timeViewModel.minutes) { ForEach(timeViewModel.minutesArray, id: \.self) { index in HStack { Text("\(index < 10 ? "0" : "")\(index)") .foregroundColor(.green) .font(.largeTitle) .frame(height: pickerRowHeight) .padding() .onTapGesture { timeViewModel.changeToMinutes = true } } } } .pickerStyle(.wheel) .frame(maxWidth: geo.size.width * 0.4) .frame(height: pickerRowHeight * 3) .clipped() .compositingGroup() .overlay { LinearGradient( colors: [.white.opacity(0.9), .clear, .white.opacity(0.9)], startPoint: .top, endPoint: .bottom ) .allowsHitTesting(false) } VStack { Text("AM") .font(.title2) .fontWeight(timeViewModel.symbol == "AM" ? .bold : .light) .foregroundColor(.orange) .onTapGesture { timeViewModel.symbol = "AM" } Text("PM") .font(.title2) .fontWeight(timeViewModel.symbol == "PM" ? .bold : .light) .foregroundColor(.orange) .onTapGesture { timeViewModel.symbol = "PM" } } } .onChange(of: timeViewModel.selectedDate) { newDate in self.numberPressed?(newDate) } HStack { Text("hour \(timeViewModel.hour)") Text("minute \(timeViewModel.minutes)") Text("\(timeViewModel.symbol)") } } } } }
修改后调整pickerRowHeight的数值即可匹配你需要的行高和总显示高度,实现3行显示的效果。
内容的提问来源于stack exchange,提问作者DanielRM
相关产品推荐
相关产品推荐

