如何在 SwiftUI 中使用多个 Picker 更改 UIPickerView 宽度?
Posted
技术标签:
【中文标题】如何在 SwiftUI 中使用多个 Picker 更改 UIPickerView 宽度?【英文标题】:How to change UIPickerView width with multiple Pickers in SwiftUI? 【发布时间】:2020-09-19 14:14:52 【问题描述】:我需要使用 UIPickerView 而不是 SwiftUI Picker,因为它存在一些错误,我需要对其进行更多控制。
下面的方法一切正常,但是,我需要一个宽度较小的选择器(大约是原始宽度的 70%),但仍然显示所有三个选择器,并且仍然具有灰色背景的圆角(所以灰色背景框架的宽度和三个选择器之间的间距应该减小)。
我尝试修改选择器的框架及其超级视图,但根本不起作用。在 SwiftUI 中设置框架宽度,然后使用 clipped 修饰符会切断圆角边缘并切断数字的某些部分(所以这是不可能的)。
有人知道怎么做吗?非常感谢!
import SwiftUI
struct ContentView: View
@State private var selections: [Int] = [5, 10, 50]
var body: some View
MainPicker(pickerSelections: self.$selections)
struct MainPicker: View
@Binding var pickerSelections: [Int]
private let data: [[String]] = [
Array(0...59).map "\($0 < 10 ? "0" : "")" + "\($0)" ,
Array(0...59).map "\($0 < 10 ? "0" : "")" + "\($0)" ,
Array(0...59).map "\($0 < 10 ? "0" : "")" + "\($0)"
]
var body: some View
HStack
PickerView(data: data, selections: self.$pickerSelections)
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 hoursLabel = UILabel()
let minLabel = UILabel()
let secLabel = UILabel()
hoursLabel.text = "h"
minLabel.text = "m"
secLabel.text = "s"
let picker = UIPickerView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) //doesnt work
picker.dataSource = context.coordinator
picker.delegate = context.coordinator
picker.superview?.frame = CGRect(x: 0, y: 0, width: 100, height: 100) //doesnt work
return picker
//updateUIView(_:context:)
func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<PickerView>)
for i in 0...(self.selections.count - 1)
if(context.coordinator.initialSelection[i] != self.selections[i])
view.selectRow(self.selections[i], inComponent: i, animated: false)
context.coordinator.initialSelection[i] = self.selections[i]
class Coordinator: NSObject, UIPickerViewDataSource, UIPickerViewDelegate
var parent: PickerView
var initialSelection = [-1, -1, -1]
//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
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
return 50
//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
【问题讨论】:
【参考方案1】:你需要去掉抗压优先
let picker = UIPickerView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
picker.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
然后可以在 SwiftUI 部分中根据需要使用任何框架(静态或计算)
MainPicker(pickerSelections: self.$selections)
.frame(width: 200)
使用 Xcode 11.7 / ios 13.7 准备和测试的演示
【讨论】:
非常感谢!完美运行(即使在 iOS 14 中使用了新的圆角)!以上是关于如何在 SwiftUI 中使用多个 Picker 更改 UIPickerView 宽度?的主要内容,如果未能解决你的问题,请参考以下文章
在 SwiftUI 中,我如何知道 Picker 选择何时更改?为啥 didSet 不起作用?
如何在 Swiftui 中与其他组件一起在 ScrollView 或 VStack 中完全显示 Picker?