#ios #swift #uidatepicker
Вопрос:
В моем приложении у меня есть кнопка, при нажатии на которую должен отображаться выбор времени с панелью инструментов на ней. В большинстве примеров я видел добавленную панель инструментов в виде ввода в текстовое поле, но в моем случае у меня нет текстового поля.
Итак, я создал пользовательское представление, в котором есть средство выбора даты и времени и панель инструментов, и я добавляю это представление в качестве подвида в представление моего контроллера, но я не вижу пользовательского представления в приложении.
Ниже приведен код контроллера для нажатия кнопки :
func buttonClicked(date: Date) {
let timePicker = EditTimeHelper.createTimePickerAndToolbar(displayDate: date)
self.view.addSubview(timePicker)
}
Код для пользовательского представления в отдельном классе EditTimeHelper:
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)
, то увижу средство выбора времени, но я хочу добавить панель инструментов поверх него.
Когда я отлаживаю этот код, я вижу средство выбора времени и панель инструментов в качестве вложенных представлений пользовательского представления, но я просто не вижу их в приложении.
Комментарии:
1. Ваш метод, создающий средство выбора, объявлен статическим. Нет экземпляра
self
, который можно было бы назначить вашему средству выбора даты.
Ответ №1:
Причина, по которой вы не видите средство выбора и панель инструментов, заключается в том, что вы неправильно расположили средство выбора времени и панель инструментов. Обратите внимание на эти две строки:
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
относится к самому классу. Когда пользователь нажимает кнопку готово, он попытается вызвать метод, вызываемый doneBtnClicked
в классе, а не в конкретном экземпляре. Но у класса нет такого метода! Объявленный doneBtnClicked
вами метод является методом экземпляра, доступным только для экземпляров.
Во-вторых, вы даете этим взглядам фиксированные позиции. Это означает, что макет будет выглядеть очень странно, когда пользователь поворачивает экран. Просто используйте автозапуск!
Вы можете сделать timeChanged
cancelBtnClicked
и doneBtnClicked
все static
такое, но гораздо лучший способ-просто создать собственный UIView
подкласс. Вот пример, в качестве отправной точки:
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?) {
}
}