如何在 SwiftUI 中使用多个选择器更改 UIPickerView 宽度? [英] How to change UIPickerView width with multiple Pickers in SwiftUI?

查看:31
本文介绍了如何在 SwiftUI 中使用多个选择器更改 UIPickerView 宽度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to use an UIPickerView instead of the SwiftUI Picker since there are some bugs with it and I need more control over it.

使用下面的方法一切正常,但是,我需要一个宽度较小的选择器(大约是原始宽度的 70%)但仍然显示所有三个选择器并且仍然具有灰色背景的圆角(所以灰色背景框宽度和三个选择器之间的间距应减小).

Everything works fine with the approach below, however, I need a picker which has a smaller width (something around 70% of the original width) but still shows all three pickers and still has the rounded corners of the gray background (so the gray background frame width and the spacing between the three pickers should decrease).

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

I tried to modify the frame of the picker and its superview but that didn't work at all. Setting the frame width in SwiftUI and then using the clipped modifier cuts off the rounded edges and also cuts off some parts of the numbers (so that's out of the question).

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

Does somebody know how to do this? Thanks a lot!

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

推荐答案

你需要去掉抗压优先

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

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

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

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

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

Demo prepared & tested with Xcode 11.7 / iOS 13.7

这篇关于如何在 SwiftUI 中使用多个选择器更改 UIPickerView 宽度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆