Fra*_*itt 4 picker uipickerview swift swiftui
我试图在SwiftUI应用程序中添加三成分选择器(UIPickerView)(在传统的UIKit应用程序中,数据源3将从该numberOfComponents方法返回),但是我在任何地方都找不到此示例。
我曾尝试添加一个由三个单一组件选择器组成的HStack,但是如果它们全部都属于一个选择器,则其透视图将与之不同。
这是上述解决方案的改编版,使用 UIKit 选择器:
import SwiftUI
struct PickerView: UIViewRepresentable {
var data: [[String]]
@Binding var selections: [Int]
//makeCoordinator()
func makeCoordinator() -> PickerView.Coordinator {
Coordinator(self)
}
//makeUIView(context:)
func makeUIView(context: UIViewRepresentableContext<PickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
return picker
}
//updateUIView(_:context:)
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<PickerView>) {
for i in 0...(self.selections.count - 1) {
view.selectRow(self.selections[i], inComponent: i, animated: false)
}
}
class Coordinator: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var parent: PickerView
//init(_:)
init(_ pickerView: PickerView) {
self.parent = pickerView
}
//numberOfComponents(in:)
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return self.parent.data.count
}
//pickerView(_:numberOfRowsInComponent:)
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.parent.data[component].count
}
//pickerView(_:titleForRow:forComponent:)
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return self.parent.data[component][row]
}
//pickerView(_:didSelectRow:inComponent:)
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.parent.selections[component] = row
}
}
}
import SwiftUI
struct ContentView: View {
private let data: [[String]] = [
Array(0...10).map { "\($0)" },
Array(20...40).map { "\($0)" },
Array(100...200).map { "\($0)" }
]
@State private var selections: [Int] = [5, 10, 50]
var body: some View {
VStack {
PickerView(data: self.data, selections: self.$selections)
Text("\(self.data[0][self.selections[0]]) \(self.data[1][self.selections[1]]) \(self.data[2][self.selections[2]])")
} //VStack
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Run Code Online (Sandbox Code Playgroud)
UIDatePickerz 做到这一点的最简单方法是使用with datePickerModeset to创建一个包装的 UI 视图.countDownTimer。
将以下代码粘贴到名为“TimeDurationPicker”的新 SwiftUI 视图文件中。选择器使用induration的值进行更新。countDownDurationDatePicker
您可以在画布上预览选择器。
struct TimeDurationPicker: UIViewRepresentable {
typealias UIViewType = UIDatePicker
@Binding var duration: TimeInterval
func makeUIView(context: Context) -> UIDatePicker {
let timeDurationPicker = UIDatePicker()
timeDurationPicker.datePickerMode = .countDownTimer
timeDurationPicker.addTarget(context.coordinator, action: #selector(Coordinator.changed(_:)), for: .valueChanged)
return timeDurationPicker
}
func updateUIView(_ uiView: UIDatePicker, context: Context) {
uiView.countDownDuration = duration
}
func makeCoordinator() -> TimeDurationPicker.Coordinator {
Coordinator(duration: $duration)
}
class Coordinator: NSObject {
private var duration: Binding<TimeInterval>
init(duration: Binding<TimeInterval>) {
self.duration = duration
}
@objc func changed(_ sender: UIDatePicker) {
self.duration.wrappedValue = sender.countDownDuration
}
}
}
struct TimeDurationPicker_Previews: PreviewProvider {
static var previews: some View {
TimeDurationPicker(duration: .constant(60.0 * 30.0))
}
}
Run Code Online (Sandbox Code Playgroud)
纯净的更新答案SwiftUI-在此示例中,数据为类型String。
已在Xcode 11.1上测试-可能无法在早期版本上使用。
struct MultiPicker: View {
typealias Label = String
typealias Entry = String
let data: [ (Label, [Entry]) ]
@Binding var selection: [Entry]
var body: some View {
GeometryReader { geometry in
HStack {
ForEach(0..<self.data.count) { column in
Picker(self.data[column].0, selection: self.$selection[column]) {
ForEach(0..<self.data[column].1.count) { row in
Text(verbatim: self.data[column].1[row])
.tag(self.data[column].1[row])
}
}
.pickerStyle(WheelPickerStyle())
.frame(width: geometry.size.width / CGFloat(self.data.count), height: geometry.size.height)
.clipped()
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
演示:
struct ContentView: View {
@State var data: [(String, [String])] = [
("One", Array(0...10).map { "\($0)" }),
("Two", Array(20...40).map { "\($0)" }),
("Three", Array(100...200).map { "\($0)" })
]
@State var selection: [String] = [0, 20, 100].map { "\($0)" }
var body: some View {
VStack(alignment: .center) {
Text(verbatim: "Selection: \(selection)")
MultiPicker(data: data, selection: $selection).frame(height: 300)
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
就像本论坛中的其他几位开发人员一样,我发现纯 SwiftUI 解决方案在 iOS 15 或更高版本中效果不佳。顺便说一句,带有 UIRepresentableView 的 UIPickerView 解决方案也不能很好地工作。高度与需要用户输入的其他视图重叠。在苹果开发者论坛上,TommyL 提出了一个非常优雅且简单的解决方案。基本上,您必须使用以下代码扩展 UIPickerView:
extension UIPickerView {
open override var intrinsicContentSize: CGSize {
return CGSize(width: UIView.noIntrinsicMetric, height: 60)
}
}
Run Code Online (Sandbox Code Playgroud)
您应该填写高度值,以防止选取器在垂直方向上延伸太多。这将限制选择器的视图和触摸区域。它适用于 Xcode 13 和 14 以及 iOS 15 及更高版本。
| 归档时间: |
|
| 查看次数: |
1536 次 |
| 最近记录: |