iOS UIPicker 高度行自动调整大小

问题描述

大家下午好。我希望一个元素的高度调整到最大尺寸。 这是我的代码示例(不起作用):

struct ContentView: View {
    private let items: [String] = [
        "<|OneLineLongggggggggggggggggggggggggggggggggggggggggg|>","<|TwoLinesLonggggggggggggg\nLongggggggggggggggg|>","<|ThreeLinesLonggggggggggggg\nLongggggggggggggggg\nLongggggggggggggggg|>"
    ]
    @State private var text: String = ""
    @State private var index: Int = 0
    var body: some View {
        BoxCustomPicker(select: self.$text,items: self.items)
    }
}
struct BoxCustomPicker : View {
    @Binding private var select: String
    private let items: [String]
    @State private var width: CGFloat = 50
    @State private var height: CGFloat = 50
    private var selectIndex: Binding<Int> {
        .init(
            get: {
                if let index = self.items.firstIndex(where: { $0 == self.select }) {
                    return index
                }
                return 0
            },set: {
                if self.items.count > $0 {
                    self.select = self.items[$0]
                }
            }
        )
    } 
    init(select: Binding<String>,items: [String]) {
        self._select = select
        self.items = items
    } 
    var body: some View {
        CustomUIPicker(width: self.$width,height: self.$height,select: self.selectIndex,items: self.items)
            .background(
                GeometryReader { proxy in
                    Color.clear
                        .onAppear {
                            let width = proxy.size.width
                            self.width = width
                            print("width: \(width)")
                        }
                }
            )
    }
}
struct CustomUIPicker : UIViewRepresentable {
    @Binding var width: CGFloat
    @Binding var height: CGFloat
    @Binding var select: Int
    let items: [String]
    func makeCoordinator() -> Self.Coordinator {
        return Self.Coordinator(self)
    }
    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIPickerView {
        let picker = UIPickerView(frame: .zero)
        picker.dataSource = context.coordinator
        picker.delegate = context.coordinator
        return picker
    }
    func updateUIView(_ view: UIPickerView,context: UIViewRepresentableContext<Self>) {
        print("updateUIView")
    }
    class Coordinator: NSObject,UIPickerViewDataSource,UIPickerViewDelegate {
        var parent: CustomUIPicker
        init(_ pickerView: CustomUIPicker) {
            self.parent = pickerView
        }
        func numberOfComponents(in pickerView: UIPickerView) -> Int {
            return 1
        }
        func pickerView(_ pickerView: UIPickerView,numberOfRowsInComponent component: Int) -> Int {
            return parent.items.count
        }
        func pickerView(_ pickerView: UIPickerView,widthForComponent component: Int) -> CGFloat {
            return self.parent.width
        }
        func pickerView(_ pickerView: UIPickerView,rowHeightForComponent component: Int) -> CGFloat {
            print("set heightRow: \(self.parent.height)")
            return self.parent.height
        }
        func pickerView(_ pickerView: UIPickerView,viewForRow row: Int,forComponent component: Int,reusing view: UIView?) -> UIView {
            let rowView: RowView = {
                if let row = view as? RowView {
                    row.frame = CGRect(x: 0,y: 0,width: self.parent.width,height: self.parent.height)
                    return row
                }
                return .init(frame: CGRect(x: 0,height: self.parent.height))
            }()
            rowView.setText(self.parent.items[row])
            let maxSize: CGSize = .init(width: self.parent.width,height: CGFloat.greatestFiniteMagnitude)
            let heightRow = rowView.sizeThatFitsText(maxSize).height
            if self.parent.height < heightRow {
                dispatchQueue.main.async {
                    self.parent.height = heightRow
                    print("update heightRow: \(heightRow)")
                    pickerView.reloadAllComponents()
                }
            }
            return rowView
        }
        func pickerView(_ pickerView: UIPickerView,didSelectRow row: Int,inComponent component: Int) {
            self.parent.select = row
        }
    }
}
extension CustomUIPicker.Coordinator {
    class RowView : UIView {
        private var label: UILabel? = nil {
            didSet {
                oldValue?.removeFromSuperview()
                if let pickerLabel = self.label {
                    self.addSubview(pickerLabel)
                    pickerLabel.translatesAutoresizingMaskIntoConstraints = false
                    let padding: CGFloat = 4
                    NSLayoutConstraint.activate([
                        pickerLabel.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor,constant: padding),pickerLabel.trailingAnchor.constraint(equalTo: self.layoutMarginsGuide.trailingAnchor,constant: -padding),pickerLabel.bottomAnchor.constraint(equalTo: self.layoutMarginsGuide.bottomAnchor,pickerLabel.leadingAnchor.constraint(equalTo: self.layoutMarginsGuide.leadingAnchor,])
                }
            }
        }
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.setupView()
        }
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            self.setupView()
        }
        public func setText(_ text: String) {
            self.label?.text = text
        }
        public func sizeThatFitsText(_ size: CGSize) -> CGSize {
            return self.label!.sizeThatFits(size)
        }
        private func setupView() {
            let pickerLabel = UILabel(frame: self.bounds)
            pickerLabel.text = ""
            pickerLabel.adjustsFontSizetoFitWidth = false
            pickerLabel.textAlignment = .center
            pickerLabel.lineBreakMode = .byCharWrapping
            pickerLabel.numberOfLines = 0
            self.label = pickerLabel
        }
    }
}

控制台输出这个日志:

updateUIView
width: 320.0
updateUIView
set heightRow: 50.0
set heightRow: 50.0
update heightRow: 61.0
updateUIView

由于某种原因,更改最大高度后不会请求元素的新高度。 结果是这样的:

enter image description here

最初,我想要一个 Picker 来调整数据并选择元素的最佳高度。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)