子类 UIControl 来制作自定义选择器
Posted
技术标签:
【中文标题】子类 UIControl 来制作自定义选择器【英文标题】:Subclass UIControl to make custom picker 【发布时间】:2017-02-06 18:37:22 【问题描述】:我正在尝试制作像 UIDatePicker
这样的自定义选择器控件,但使用不同的数据源来包含选择器的所有逻辑,并允许目标操作行为。
为此,我将UIControl
子类化,添加UIPickerView
并设置选择器视图的数据源和委托给子类。我的问题在于视图的大小。
我在每个设备上都使用过UIDatePicker
,它的默认高度是 216,默认宽度是 320。拉伸宽度时,选择器视图不会拉伸,但拉伸高度时会拉伸。为了适应系统,我希望我的选择器的大小也一样。
我尝试为我的子类制作一个 nib 文件。我将视图调整为 320x216,添加了 UIPickerView
并将其连接为 IBOutlet
。在我对init?(coder aDecoder: NSCoder)
的实现中,我设置了选择器的数据源和委托,但是当我运行我的测试应用程序时,我崩溃了,因为此时连接的UIPickerView
仍然是nil
。
我的目标是能够使用 init()
和在情节提要中使用它,就像使用 UIDatePicker
一样,所以我放弃了 nib 并一直试图将所有内容封装在代码中。如何将视图设置为与 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
【问题讨论】:
【参考方案1】:您只需将您的pickerView
作为子视图添加到您的FWHeightPicker
。然后,您应该使用 pickerView.translatesAutoresizingMaskIntoConstraints = false
删除 pickerView
的默认 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"
【讨论】:
以上是关于子类 UIControl 来制作自定义选择器的主要内容,如果未能解决你的问题,请参考以下文章
在警报级别窗口中具有自定义 inputView 的 UIControl
UIControl 跟踪在不同 UIControl 上开始的触摸