如何在 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 多个错误,核心数据,布局

在 SwiftUI 中,我如何知道 Picker 选择何时更改?为啥 didSet 不起作用?

如何在 Swiftui 中与其他组件一起在 ScrollView 或 VStack 中完全显示 Picker?

SwiftUI 从另一个视图中捕获 Picker 值

SwiftUI 如何让 ForEach 循环根据 Picker 中选定月份的天数进行迭代

在 SwiftUI 的 Picker 中添加新元素