如何在SwiftUI中使用多个选择器更改UIPickerView宽度?

时间:2020-09-19 14:14:52

标签: ios swift swiftui uikit

我需要使用UIPickerView而不是SwiftUI Picker,因为它存在一些错误,我需要对其进行更多控制。

一切都可以用下面的方法很好地工作,但是,我需要一个宽度较小的拾取器(大约是原始宽度的70%),但仍然显示所有三个拾取器,并且仍然具有灰色背景的圆角(因此灰色背景框宽度和三个拾取器之间的间距应减小)。

我试图修改选择器的框架及其超级视图,但这根本不起作用。在SwiftUI中设置帧宽度,然后使用clipped修饰符可以剪切圆角边缘,也可以剪切数字的某些部分(因此这是不可能的)。

有人知道该怎么做吗?非常感谢!

enter image description here

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 个答案:

答案 0 :(得分:1)

您需要删除抗压缩优先级

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

然后可以根据需要在SwiftUI部分使用任何框架(静态或计算)

demo

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

使用Xcode 11.7 / iOS 13.7准备和测试的演示