Multi-Component Picker (Uipickerview) in Swiftui

Multi-Component Picker (UIPickerView) in SwiftUI

Here's an adaptation of the solutions above, using the UIKit picker:

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()
}
}

How to change UIPickerView width with multiple Pickers in SwiftUI?

You need to remove compression resistance priority

let picker = UIPickerView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
picker.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

and then can use any frame as you need in SwiftUI part (static or calculated)

demo

    MainPicker(pickerSelections: self.$selections)
.frame(width: 200)

Demo prepared & tested with Xcode 11.7 / iOS 13.7

SwiftUI: How to center multi column picker on screen

Not really sure the final goal, but for provided code it can be done just by making Stack consume all space provided by GeometryReader, like

HStack{

// ... other code here

}
.frame(maxWidth: .infinity) // << this one !!

Tested with Xcode 12.4 / iOS 14.4

demo

SwiftUI - Placing two pickers side-by-side in HStack does not resize pickers

The overlapping in the middle you can fix by adding a clipped() modifier. As for the width, I see them both exactly the same:

Sample Image

struct ContentView: View {
@State var selection1: Int = 0
@State var selection2: Int = 0

@State var integers: [Int] = [0, 1, 2, 3, 4, 5]

var body: some View {
GeometryReader { geometry in
HStack(spacing: 0) {
Picker(selection: self.$selection1, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: geometry.size.width / 2)
.clipped()
.border(Color.red)

Picker(selection: self.$selection2, label: Text("Numbers")) {
ForEach(self.integers) { integer in
Text("\(integer)")
}
}
.frame(maxWidth: geometry.size.width / 2)
.clipped()
.border(Color.blue)
}
}
}
}


Related Topics



Leave a reply



Submit