For large fonts, the lines in a Picker
are overlapping. How do I change the Picker's
line height? (Hint: the .lineSpacing
modifier doesn't do it.)
See Also
This question is similar to that of Ejaaz, but his is so far unanswered.
The Problem
The Code
The following runnable code yields the above result. I don't really want different-sized lines, I just want the large fonts to fit properly. I have tried inserting Spacers
, adding .frame
modifiers here and there, .lineSpacing
, padding()
... maybe just haven't found the right combination?
struct ContentView: View {
@State private var selected = 0
var body: some View {
Picker(selection: self.$selected, label: Text("Letters")) {
Text("A").font(.system(size: 30))
Text("B").font(.system(size: 40))
Text("C").font(.system(size: 50))
Text("D").font(.system(size: 60))
Text("E").font(.system(size: 70))
Text("F").font(.system(size: 80))
}
}
}
You have to wrap UIPickerView
in a UIViewRepresentable
and then use:
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
… to change your row height.
It just shows how to change row height, you still have to extend it for your contents...
struct PickerView: UIViewRepresentable {
var data: [[String]]
@Binding var selections: Int
// Assign custom coordinator for delegate functions.
func makeCoordinator() -> PickerView.Coordinator {
Coordinator(self)
}
// Creates the view object and configures its initial state.
func makeUIView(context: UIViewRepresentableContext<PickerView>) -> UIPickerView {
let picker = UIPickerView(frame: .zero)
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
return picker
}
// Updates the state of the specified view with new information from SwiftUI.
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<PickerView>) {
// for i in 0...(self.selections.count - 1) {
// view.selectRow(self.selections[i], inComponent: i, animated: false)
// }
}
// Coordinator acting as the delegate in SwiftUI.
class Coordinator: NSObject, UIPickerViewDataSource, UIPickerViewDelegate {
var parent: PickerView
//init(_:)
init(_ pickerView: PickerView) {
self.parent = pickerView
}
// Set your custom row height here!
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 80
}
//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
}
}
}
To use it in your SwiftUI view, simply place the custom PickerView()
in your body.