带工具栏但没有文本字段的 UIDatePicker
UIDatePicker with toolbar but without text field
在我的应用程序中,我有一个按钮,单击该按钮时应显示带有工具栏的时间选择器。大多数示例我看到添加的工具栏作为文本字段上的 inputAccessoryView,但在我的例子中我没有文本字段。
因此,我创建了一个自定义视图,其中包含日期时间选择器和工具栏,我将该视图作为子视图添加到我的控制器视图中,但我没有在应用程序上看到自定义视图。
下面是点击按钮的控制器代码:
func buttonClicked(date: Date) {
let timePicker = EditTimeHelper.createTimePickerAndToolbar(displayDate: date)
self.view.addSubview(timePicker)
}
单独的 EditTimeHelper 中的自定义视图代码 class:
static func createTimePickerAndToolbar(displayDate: Date) -> UIView {
let pickerView = UIView(frame: CGRect(x: 0, y: UIScreen.main.bounds.height - 300, width: UIScreen.main.bounds.width, height: 300))
let timePicker = createTimePicker(displayDate: displayDate)
pickerView.addSubview(timePicker)
let toolbar = createUIToolBar()
pickerView.addSubview(toolbar)
return pickerView
}
static func createTimePicker(displayDate: Date) -> UIDatePicker {
let timePicker:UIDatePicker = UIDatePicker()
timePicker.datePickerMode = UIDatePicker.Mode.time
timePicker.date = displayDate
timePicker.minuteInterval = 15
if #available(iOS 13.4, *) {
timePicker.preferredDatePickerStyle = .wheels
} else {
// Fallback on earlier versions where time picker is wheels style by default.
}
timePicker.addTarget(self, action: #selector(timeChanged(_:)), for: UIControl.Event.valueChanged)
timePicker.backgroundColor = .white
timePicker.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 200, width: UIScreen.main.bounds.width, height: 200)
return timePicker
}
private static func createUIToolBar() -> UIToolbar {
let pickerToolbar = UIToolbar()
pickerToolbar.autoresizingMask = .flexibleHeight
//customize the toolbar
pickerToolbar.barStyle = .default
pickerToolbar.barTintColor = UIColor.black
pickerToolbar.backgroundColor = UIColor.white
pickerToolbar.isTranslucent = false
pickerToolbar.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 300, width: UIScreen.main.bounds.width, height: 100)
// add buttons
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelBtnClicked(_:)))
cancelButton.tintColor = UIColor.white
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneBtnClicked(_:)))
doneButton.tintColor = UIColor.white
//add the items to the toolbar
pickerToolbar.items = [cancelButton, flexSpace, doneButton]
return pickerToolbar
}
@objc func timeChanged(_ sender: UIDatePicker) {
}
@objc func cancelBtnClicked(_ button: UIBarButtonItem?) {
}
@objc func doneBtnClicked(_ button: UIBarButtonItem?) {
}
知道我做错了什么没有看到自定义视图吗?
如果我调用 EditTimeHelper.createTimePicker(displatDate: date)
,我会看到时间选择器,但我想在它上面添加工具栏。
当我调试这段代码时,我确实看到时间选择器和工具栏作为自定义视图的子视图,但我只是没有在应用程序上看到它们。
你看不到时间选择器和工具栏的原因是时间选择器和工具栏的位置不正确。注意这两行:
timePicker.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 200, width: UIScreen.main.bounds.width, height: 200)
// and
pickerToolbar.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 300, width: UIScreen.main.bounds.width, height: 100)
因为这些是 pickerView
的子视图,坐标是相对于 pickerView
的左上角,而不是屏幕的左上角。你应该改为
timePicker.frame = CGRect(x: 0, y: 100, width: UIScreen.main.bounds.width, height: 200)
// and
pickerToolbar.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 100)
现在您应该会看到工具栏和时间选择器。
但是,您的代码还有其他问题。首先,timeChanged
、cancelBtnClicked
和 doneBtnClicked
不会被调用。您已将 self
添加为栏按钮项和选择器的目标,但由于您使用的是静态方法,因此 self
指的是 class 本身。当用户按下完成按钮时,它会尝试在 class 上调用名为 doneBtnClicked
的方法,而不是调用特定实例。但是class没有这样的方法!您声明的 doneBtnClicked
是一个实例方法,仅在实例上可用。
其次,你给了这些观点固定的位置。这意味着当用户旋转屏幕时布局看起来会很奇怪。 只需使用自动版式!
您也可以将 timeChanged
、cancelBtnClicked
和 doneBtnClicked
都设置为 static
,但更好的方法是创建自定义 UIView
子class。这是一个例子,作为起点:
class TimePickerToolBarView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
let timePicker = createTimePicker()
addSubview(timePicker)
let toolBar = createUIToolBar()
addSubview(toolBar)
timePicker.translatesAutoresizingMaskIntoConstraints = false
toolBar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
toolBar.heightAnchor.constraint(equalToConstant: 44),
toolBar.topAnchor.constraint(equalTo: topAnchor),
toolBar.leftAnchor.constraint(equalTo: leftAnchor),
toolBar.rightAnchor.constraint(equalTo: rightAnchor),
timePicker.leftAnchor.constraint(equalTo: leftAnchor),
timePicker.rightAnchor.constraint(equalTo: rightAnchor),
timePicker.bottomAnchor.constraint(equalTo: bottomAnchor),
timePicker.topAnchor.constraint(equalTo: toolBar.bottomAnchor),
])
}
private func createTimePicker() -> UIDatePicker {
let timePicker:UIDatePicker = UIDatePicker(frame: .zero)
timePicker.datePickerMode = UIDatePicker.Mode.time
timePicker.minuteInterval = 15
if #available(iOS 13.4, *) {
timePicker.preferredDatePickerStyle = .wheels
} else {
// Fallback on earlier versions where time picker is wheels style by default.
}
timePicker.addTarget(self, action: #selector(timeChanged(_:)), for: UIControl.Event.valueChanged)
timePicker.backgroundColor = .white
return timePicker
}
private func createUIToolBar() -> UIToolbar {
let pickerToolbar = UIToolbar(frame: .zero)
//customize the toolbar
pickerToolbar.barStyle = .default
pickerToolbar.barTintColor = UIColor.black
pickerToolbar.backgroundColor = UIColor.white
pickerToolbar.isTranslucent = false
// add buttons
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelBtnClicked(_:)))
cancelButton.tintColor = UIColor.white
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneBtnClicked(_:)))
doneButton.tintColor = UIColor.white
//add the items to the toolbar
pickerToolbar.items = [cancelButton, flexSpace, doneButton]
return pickerToolbar
}
@objc func timeChanged(_ sender: UIDatePicker) {
}
@objc func cancelBtnClicked(_ button: UIBarButtonItem?) {
}
@objc func doneBtnClicked(_ button: UIBarButtonItem?) {
}
}
在我的应用程序中,我有一个按钮,单击该按钮时应显示带有工具栏的时间选择器。大多数示例我看到添加的工具栏作为文本字段上的 inputAccessoryView,但在我的例子中我没有文本字段。
因此,我创建了一个自定义视图,其中包含日期时间选择器和工具栏,我将该视图作为子视图添加到我的控制器视图中,但我没有在应用程序上看到自定义视图。
下面是点击按钮的控制器代码:
func buttonClicked(date: Date) {
let timePicker = EditTimeHelper.createTimePickerAndToolbar(displayDate: date)
self.view.addSubview(timePicker)
}
单独的 EditTimeHelper 中的自定义视图代码 class:
static func createTimePickerAndToolbar(displayDate: Date) -> UIView {
let pickerView = UIView(frame: CGRect(x: 0, y: UIScreen.main.bounds.height - 300, width: UIScreen.main.bounds.width, height: 300))
let timePicker = createTimePicker(displayDate: displayDate)
pickerView.addSubview(timePicker)
let toolbar = createUIToolBar()
pickerView.addSubview(toolbar)
return pickerView
}
static func createTimePicker(displayDate: Date) -> UIDatePicker {
let timePicker:UIDatePicker = UIDatePicker()
timePicker.datePickerMode = UIDatePicker.Mode.time
timePicker.date = displayDate
timePicker.minuteInterval = 15
if #available(iOS 13.4, *) {
timePicker.preferredDatePickerStyle = .wheels
} else {
// Fallback on earlier versions where time picker is wheels style by default.
}
timePicker.addTarget(self, action: #selector(timeChanged(_:)), for: UIControl.Event.valueChanged)
timePicker.backgroundColor = .white
timePicker.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 200, width: UIScreen.main.bounds.width, height: 200)
return timePicker
}
private static func createUIToolBar() -> UIToolbar {
let pickerToolbar = UIToolbar()
pickerToolbar.autoresizingMask = .flexibleHeight
//customize the toolbar
pickerToolbar.barStyle = .default
pickerToolbar.barTintColor = UIColor.black
pickerToolbar.backgroundColor = UIColor.white
pickerToolbar.isTranslucent = false
pickerToolbar.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 300, width: UIScreen.main.bounds.width, height: 100)
// add buttons
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelBtnClicked(_:)))
cancelButton.tintColor = UIColor.white
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneBtnClicked(_:)))
doneButton.tintColor = UIColor.white
//add the items to the toolbar
pickerToolbar.items = [cancelButton, flexSpace, doneButton]
return pickerToolbar
}
@objc func timeChanged(_ sender: UIDatePicker) {
}
@objc func cancelBtnClicked(_ button: UIBarButtonItem?) {
}
@objc func doneBtnClicked(_ button: UIBarButtonItem?) {
}
知道我做错了什么没有看到自定义视图吗?
如果我调用 EditTimeHelper.createTimePicker(displatDate: date)
,我会看到时间选择器,但我想在它上面添加工具栏。
当我调试这段代码时,我确实看到时间选择器和工具栏作为自定义视图的子视图,但我只是没有在应用程序上看到它们。
你看不到时间选择器和工具栏的原因是时间选择器和工具栏的位置不正确。注意这两行:
timePicker.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 200, width: UIScreen.main.bounds.width, height: 200)
// and
pickerToolbar.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 300, width: UIScreen.main.bounds.width, height: 100)
因为这些是 pickerView
的子视图,坐标是相对于 pickerView
的左上角,而不是屏幕的左上角。你应该改为
timePicker.frame = CGRect(x: 0, y: 100, width: UIScreen.main.bounds.width, height: 200)
// and
pickerToolbar.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 100)
现在您应该会看到工具栏和时间选择器。
但是,您的代码还有其他问题。首先,timeChanged
、cancelBtnClicked
和 doneBtnClicked
不会被调用。您已将 self
添加为栏按钮项和选择器的目标,但由于您使用的是静态方法,因此 self
指的是 class 本身。当用户按下完成按钮时,它会尝试在 class 上调用名为 doneBtnClicked
的方法,而不是调用特定实例。但是class没有这样的方法!您声明的 doneBtnClicked
是一个实例方法,仅在实例上可用。
其次,你给了这些观点固定的位置。这意味着当用户旋转屏幕时布局看起来会很奇怪。 只需使用自动版式!
您也可以将 timeChanged
、cancelBtnClicked
和 doneBtnClicked
都设置为 static
,但更好的方法是创建自定义 UIView
子class。这是一个例子,作为起点:
class TimePickerToolBarView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
let timePicker = createTimePicker()
addSubview(timePicker)
let toolBar = createUIToolBar()
addSubview(toolBar)
timePicker.translatesAutoresizingMaskIntoConstraints = false
toolBar.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
toolBar.heightAnchor.constraint(equalToConstant: 44),
toolBar.topAnchor.constraint(equalTo: topAnchor),
toolBar.leftAnchor.constraint(equalTo: leftAnchor),
toolBar.rightAnchor.constraint(equalTo: rightAnchor),
timePicker.leftAnchor.constraint(equalTo: leftAnchor),
timePicker.rightAnchor.constraint(equalTo: rightAnchor),
timePicker.bottomAnchor.constraint(equalTo: bottomAnchor),
timePicker.topAnchor.constraint(equalTo: toolBar.bottomAnchor),
])
}
private func createTimePicker() -> UIDatePicker {
let timePicker:UIDatePicker = UIDatePicker(frame: .zero)
timePicker.datePickerMode = UIDatePicker.Mode.time
timePicker.minuteInterval = 15
if #available(iOS 13.4, *) {
timePicker.preferredDatePickerStyle = .wheels
} else {
// Fallback on earlier versions where time picker is wheels style by default.
}
timePicker.addTarget(self, action: #selector(timeChanged(_:)), for: UIControl.Event.valueChanged)
timePicker.backgroundColor = .white
return timePicker
}
private func createUIToolBar() -> UIToolbar {
let pickerToolbar = UIToolbar(frame: .zero)
//customize the toolbar
pickerToolbar.barStyle = .default
pickerToolbar.barTintColor = UIColor.black
pickerToolbar.backgroundColor = UIColor.white
pickerToolbar.isTranslucent = false
// add buttons
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelBtnClicked(_:)))
cancelButton.tintColor = UIColor.white
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneBtnClicked(_:)))
doneButton.tintColor = UIColor.white
//add the items to the toolbar
pickerToolbar.items = [cancelButton, flexSpace, doneButton]
return pickerToolbar
}
@objc func timeChanged(_ sender: UIDatePicker) {
}
@objc func cancelBtnClicked(_ button: UIBarButtonItem?) {
}
@objc func doneBtnClicked(_ button: UIBarButtonItem?) {
}
}