我有一个ViewController
和两个UITextFields
,它们使用UIDatePicker(s)
进行输入。一个是“开始”日期,另一个是“结束”日期,因此这似乎是很常见的情况。
问题在于,当一个字段的DatePicker处于活动状态时,用户可以点击屏幕上的另一个字段。活动的DatePicker仍然绑定到第一个字段,因此UI会使用户感到困惑,因为光标在另一个字段中闪烁,但输入没有在那里。
我认为正确的UI解决方案是防止用户点击其他任何字段,直到关闭DatePicker。但是我一直无法找到一种方法来检测firstResponder正在更改,或者暂时禁用其他字段的编辑。
这是我当前的代码无法满足我的需要:
class AddTripLocationVC: UIViewController, UITextFieldDelegate {
@IBOutlet private weak var tripLocFromDateInput: UITextField!
@IBOutlet private weak var tripLocToDateInput: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//set up datepickers for text field inputs
createDatePicker(forDateField: tripLocFromDateInput)
createDatePicker(forDateField: tripLocToDateInput)
}
//automatically update the label fields when the date vairables are updated by the UIDatePicker
var locFromDate: Date? {
didSet {
guard locFromDate != nil else { return }
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
tripLocFromDateInput.text = dateFormatter.string(from: locFromDate!)
}
}
var locToDate: Date? {
didSet {
guard locToDate != nil else { return }
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
tripLocFromDateInput.text = dateFormatter.string(from: locToDate!)
//Comment after solution found...The problem was the line above
//It should be:
tripLocToDateInput.text = dateFormatter.string(from: locToDate!)
}
}
func createDatePicker(forDateField dateField: UITextField) {
let datePickerView = UIDatePicker()
datePickerView.datePickerMode = .date
dateField.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
let doneButton = UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(self.datePickerDone))
let toolBar = UIToolbar.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 44))
toolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil), doneButton],
animated: true)
dateField.inputAccessoryView = toolBar
}
@objc
func handleDatePicker(sender: UIDatePicker) {
if tripLocFromDateInput.isFirstResponder {
locFromDate = sender.date
} else {
if tripLocToDateInput.isFirstResponder {
locToDate = sender.date
} else {
print("Error: Can't find first responder field.")
}
}
}
@objc
func datePickerDone(dateField: UITextView) {
if tripLocFromDateInput.isFirstResponder {
tripLocFromDateInput.resignFirstResponder()
} else {
if tripLocToDateInput.isFirstResponder {
tripLocToDateInput.resignFirstResponder()
} else {
print("Error: Can't find first responder field.")
}
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldDidEndEditing(_ textField: UITextField) {
textField.becomeFirstResponder()
}
}
在iOS中,对于这种类型的“从”和“到”日期字段,是否有“标准”的UI方法?
答案 0 :(得分:0)
您可以注册一个UITextField委托,其中包含两个您特别感兴趣的方法,
textFieldDidBeginEditing(:)
textFieldDidEndEditing(:)
要获取更多信息,请访问:https://developer.apple.com/documentation/uikit/uitextfielddelegate
请注意,您还可以在任何UITextField上使用becomeFirstResponder()
来激活一个。处于活动状态的光标应该闪烁。
编辑:根据您更新的代码:
//
// ViewController.swift
// datepickers
//
// Created by Dave Poirier on 2019-06-13.
//
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet private weak var tripLocFromDateInput: UITextField!
@IBOutlet private weak var tripLocToDateInput: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//set up datepickers for text field inputs
createDatePicker(forDateField: tripLocFromDateInput)
createDatePicker(forDateField: tripLocToDateInput)
//set text field delegates to be notified when focus changes
tripLocFromDateInput.delegate = self
tripLocToDateInput.delegate = self
}
func createDatePicker(forDateField dateField: UITextField) {
let datePickerView = UIDatePicker()
datePickerView.datePickerMode = .date
dateField.inputView = datePickerView
datePickerView.addTarget(self, action: #selector(handleDatePicker(sender:)), for: .valueChanged)
let doneButton = UIBarButtonItem.init(title: "Done", style: .done, target: self, action: #selector(self.datePickerDone))
let toolBar = UIToolbar.init(frame: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: 44))
toolBar.setItems([UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil), doneButton],
animated: true)
dateField.inputAccessoryView = toolBar
}
@objc
func handleDatePicker(sender: UIDatePicker) {
if tripLocFromDateInput.isFirstResponder {
let locFromDate = sender.date
tripLocFromDateInput.text = "FROM: \(locFromDate)"
} else {
if tripLocToDateInput.isFirstResponder {
let locToDate = sender.date
tripLocToDateInput.text = "TO: \(locToDate)"
} else {
print("Error: Can't find first responder field.")
}
}
}
@objc
func datePickerDone(dateField: UITextView) {
if tripLocFromDateInput.isFirstResponder {
tripLocFromDateInput.resignFirstResponder()
} else {
if tripLocToDateInput.isFirstResponder {
tripLocToDateInput.resignFirstResponder()
} else {
print("Error: Can't find first responder field.")
}
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
self.view.endEditing(true)
}
}
}
上面的代码在一个全新的项目中为我工作,创建了两个输入字段并连接了IBOutlets