子类UIControl以进行自定义选取器



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

为此,我将对UIControl进行子类化,添加一个UIPickerView,并将picker视图的数据源和委托设置为子类。我的问题在于视图的大小。

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

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

我的目标是能够使用init()和在故事板中使用它,就像使用UIDatePicker一样,所以我放弃了笔尖,一直试图将所有内容封装在代码中。如何设置视图以使其行为与UIDatePicker相同?

这是我目前的尝试(不使用笔尖,因为它必须在代码中才能在故事板中使用):

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
}

您只需要将pickerView作为子视图添加到FWHeightPicker中即可。然后,应该将pickerView的默认自动布局约束与pickerView.translatesAutoresizingMaskIntoConstraints = false一起删除,以使用所需的约束。

我已经对你的代码进行了一些处理(只是为了方便起见删除了扩展)-它工作得很好,可以拉伸/缩小选择器的宽度和高度,以适应你的便利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"
}
}

最新更新