【问题标题】:How do you add a button to a UIPickerView?如何向 UIPickerView 添加按钮?
【发布时间】:2021-04-19 21:16:53
【问题描述】:

如何向 UIPickerView 添加一个可用于关闭或隐藏 PickerView 的按钮?

我找到了一些解决这些问题的方法,但很多似乎都没有找到我想要的答案。 This 问题是我能找到的最接近我所问的问题,但它已经过时了,所以我想展示我的解决方案。我有一个 UIPickerView 的子类,我想添加一个 UIButton 以便能够关闭它。我想要一个内部带有 UIToolBar 的 UIPickerView。

下图准确描述了我正在寻找的将完成按钮添加到我的 UIPickerView 子类的位置

您需要做的只是向 UIPickerView 添加一个 UIButton 并添加一个目标以调用方法,这似乎微不足道,因为我还希望 PickerView 响应用户对行的选择,按下 Done 按钮导致没有回应

【问题讨论】:

  • 您还没有解释解雇的含义。选择器首先是如何出现的?作为屏幕底部的键盘?

标签: ios swift uibutton uipickerview


【解决方案1】:

这样创建 UIView 的子类

class CustomViewWithPicker: UIView {
    
    let picker = UIPickerView(frame: .zero)
    let pickerTitle = UILabel(frame: .zero)
    let button = UIButton(frame: .zero)
    
    let title: String = "Picker Title"
    let buttonName: String = "Button"
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        didLoad()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        didLoad()
    }
    
    func didLoad() {
        
        self.addSubview(picker)
        self.addSubview(pickerTitle)
        self.addSubview(button)
        
        picker.backgroundColor = .tertiarySystemBackground
        picker.layer.cornerRadius = 20
        picker.frame = .zero
        
        pickerTitle.text = title
        pickerTitle.font = .boldSystemFont(ofSize: 22)
        pickerTitle.textAlignment = .center
        pickerTitle.backgroundColor = .tertiarySystemBackground
        
        button.setTitle(buttonName, for: .normal)
        button.contentHorizontalAlignment = .right
        button.contentVerticalAlignment = .top
        button.isSelected = true
        
        self.updateConstraints()
    }
    
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if self.point(inside: point, with: event) {
            return super.hitTest(point, with: event)
        }
        guard isUserInteractionEnabled, !isHidden, alpha > 0 else {
            return nil
        }
        
        for subview in subviews.reversed() {
            let convertedPoint = subview.convert(point, from: self)
            if let hitView = subview.hitTest(convertedPoint, with: event) {
                return hitView
            }
        }
        return nil
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
    }
    
    override func updateConstraints() {
        // Make Constraints ...
    }
}

在ViewController中符合UIPickerViewDelegate和UIPickerViewDataSource

class MyViewController : UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UIGestureRecognizerDelegate {
    
    let customView = CustomViewWithPicker()
    let labels = ["label0", "label1", "label2", "label3", "label4", "label5"]
    var selectedRow = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        
        customView.picker.delegate = self
        customView.picker.dataSource = self

        customView.button.addTarget(self, action: #selector(doneButtonTapped(_:)), for: .touchUpInside)
        
        self.view.addSubview(customView)
        
    }
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        1
    }
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return labels.count
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return labels[row]
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        selectedRow = row
    }
    
    @objc func doneButtonTapped(_ selectedButton: UIButton) {
        if selectedButton.isSelected {
            print("Done Button Tapped")
        }
    }
}

我到处寻找一个 UIPickerView 实现,它不依赖 UIToolBar 来检测按钮上的点击,但无济于事。

感谢 Duncan C. 的意见和建议

【讨论】:

  • Apple 通常会说不要破坏其组件的视图层次结构。将子视图添加到 UIPickerView 的子类是脆弱的,不推荐。
【解决方案2】:

简短回答:不要那样做。

Apple 表示不要弄乱其组件的视图层次结构。您应该创建一个包含选择器和按钮的组件,并使它们看起来像一个单一的、多部分的组件。这样,如果 Apple 在未来的版本中更改 UIPickerView 的内部结构,它不会破坏你。

【讨论】:

  • 那么,这个由多部分组成的组件会是 UIView 的子类吗?您是否碰巧有一个指向 Apple 文档的链接,该链接可能解释了将 UIKit 元素子类化的更好方法?
  • 我试图在 Apple 的文档中找到它说不要弄乱其专用 UI​​View 组件的视图层次结构(如选择器视图、表格视图、集合视图、滑块等)但找不到找到它。如果您创建一个包含选择器和其他视图的复合视图,您可能不需要子类化 UIPickerView。
  • 我明白了,所以使用 UILabel、UIPickerView 和 UIButton 属性子类化 UIView 可能是最佳实践?
  • 这是我的建议,是的。如果您将 UIPickerView 子类化并向其添加子视图,那么在将来的某个日期,Apple 会更改基类的几何形状或行为,它们可能会破坏您。 (基本指导是只依赖于框架类的文档化公共接口。如果你依赖于它们当前在内部实现的某些不属于公共合同的内容的方式,那么你就会依赖于该内部实现,并且很脆弱。)跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 2015-03-29
  • 2012-11-09
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多