子类UIControl来制作自定义选择器

时间:2017-02-06 18:37:22

标签: ios autolayout uidatepicker uicontrol

我正在尝试创建一个自定义选择器控件,如UIDatePicker,但使用不同的数据源来包含选择器的所有逻辑,并允许目标操作行为。

为此,我正在继承UIControl,添加UIPickerView并设置选择器视图的数据源并委托给子类。我的问题在于观点的大小。

我在每个设备上玩过UIDatePicker,它的默认高度是216,默认宽度是320.当拉伸宽度时,拾取器视图不会拉伸,但是当拉伸高度时确实。为了适应系统,我希望我的选择器的大小相同。

我尝试为我的子类创建一个nib文件。我将视图调整为320x216,添加了UIPickerView并将其连接为IBOutlet。在我init?(coder aDecoder: NSCoder)的实现中,我设置了选择器的数据源和委托,但是当我运行我的测试应用时,我崩溃了,因为此时连接的UIPickerView仍然是nil

我的目标是能够使用init()UIDatePicker中的故事板一起使用它,所以我抛弃了笔尖并且一直在尝试将所有内容封装在代码中。如何将视图设置为与UIDatePicker

相同的行为

这是我当前的尝试(不使用nib,因为它必须在代码中用于故事板):

class FWHeightPicker: UIControl {
    let pickerView: UIPickerView

    convenience init() {
        let size = CGSize(width: 320, height: 216)
        let origin = CGPoint(x: 0, y: 0)
        let frame = CGRect(origin: origin, size: size)

        self.init(frame: frame)
    }

    override init(frame: CGRect) {
        pickerView = UIPickerView(frame: frame)

        super.init(frame: frame)
        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        let size = CGSize(width: 320, height: 216)
        let origin = CGPoint(x: 0, y: 0)
        let frame = CGRect(origin: origin, size: size)

        pickerView = UIPickerView(frame: frame)

        super.init(coder: aDecoder)
        commonInit()
    }

    func commonInit() {
        let topConstraint = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: pickerView, attribute: .top, multiplier: 1, constant: 0)
        let bottomConstraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: pickerView, attribute: .bottom, multiplier: 1, constant: 0)
        self.addConstraints([topConstraint, bottomConstraint])

        pickerView.delegate = self
        pickerView.dataSource = self
    }
}

extension FWHeightPicker: UIPickerViewDelegate, UIPickerViewDataSource {
// Delegate/Datasource implementations
}

1 个答案:

答案 0 :(得分:0)

您应该将pickerView作为子视图添加到FWHeightPicker。然后,您应该使用pickerView删除pickerView.translatesAutoresizingMaskIntoConstraints = false的默认AutoLayout约束,以支持您所需的约束。

我已经玩了一些你的代码(为了方便我只删除了扩展名) - 它工作得很好,并且拉伸/缩小了选择器的宽度和高度,以适应你方便定义的视图大小的init():

class FWHeightPicker: UIControl, UIPickerViewDelegate, UIPickerViewDataSource {

  let pickerView: UIPickerView

  convenience init() {

    let size = CGSize(width: 320, height: 216)
    let origin = CGPoint(x: 0, y: 0)
    let frame = CGRect(origin: origin, size: size)

    self.init(frame: frame)
  }

  override init(frame: CGRect) {

    pickerView = UIPickerView(frame: frame)

    super.init(frame: frame)
    commonInit()
  }

  required init?(coder aDecoder: NSCoder) {

    pickerView = UIPickerView()

    super.init(coder: aDecoder)
    commonInit()
  }

  func commonInit() {

    pickerView.delegate = self
    pickerView.dataSource = self

    addSubview(pickerView)

    pickerView.translatesAutoresizingMaskIntoConstraints = false

    let topConstraint = NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: pickerView, attribute: .top, multiplier: 1, constant: 0)

    let bottomConstraint = NSLayoutConstraint(item: pickerView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0)

    let leftConstraint = NSLayoutConstraint(item: self, attribute: .leading, relatedBy: .equal, toItem: pickerView, attribute: .leading, multiplier: 1.0, constant: 0)

    let rightConstraint = NSLayoutConstraint(item: pickerView, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: 0)

    self.addConstraints([topConstraint, bottomConstraint, leftConstraint, rightConstraint])

  }

  // Delegate/Datasource implementations
  func numberOfComponents(in pickerView: UIPickerView) -> Int {

    return 1
  }

  func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {

    return 10
  }

  func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

    return "row"
  }
}