BecomeFirstResponder и множественный фокус UITextField
Итак, у меня есть представление -> UITextField и UILabel - это два дочерних элемента, у меня есть несколько представлений, которые содержат дочерние элементы. Я использую функцию делегата ниже, и я назначаю каждое из полей UIText в качестве делегатов "textFieldShouldReturn(_ textField: UITextField) -> Bool". Тем не менее, они не изменяют фокус TextField, когда я нажимаю клавишу возврата. При использовании этой техники фокусировки с UITextFields без их вложения в представление. Это позволяет мне менять фокус без проблем. Почему вложение UITextField в представлении приводит к невозможности сделать следующий UITextField первым респондентом? Я прочитал несколько вещей о первом респондере и о том, как он работает, но он не дает четкого объяснения, как обойти эту проблему.
class ScrollingViewWithFields:UIViewController, UITextFieldDelegate {
let scrollView = UIScrollView()
let contentView = UIView()
var textFields:[UITextField] = []
var labeledTextField:[LabeledTextField] = []
override func viewDidLoad() {
contentView.backgroundColor = UIColor.white
contentView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
scrollView.addSubview(contentView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.backgroundColor = UIColor.white
let top = view.safeAreaLayoutGuide.topAnchor
let bottom = view.safeAreaLayoutGuide.bottomAnchor
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: top),
scrollView.bottomAnchor.constraint(equalTo: bottom),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor)
])
let ltf = LabeledTextField()
ltf.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(ltf)
ltf.populate(title: "Hello", font: UIFont.systemFont(ofSize: 14.0))
ltf.textField.delegate = self
ltf.textField.tag = 0
let ltf2 = LabeledTextField()
ltf2.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(ltf2)
ltf2.populate(title: "What", font: UIFont.systemFont(ofSize: 14.0))
ltf2.textField.tag = 1
ltf2.textField.delegate = self
self.textFields.append(ltf2.textField)
self.textFields.append(ltf.textField)
NSLayoutConstraint.activate([
ltf.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8.0),
ltf.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0),
ltf.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 8.0),
ltf.heightAnchor.constraint(equalToConstant: 60)
])
NSLayoutConstraint.activate([
ltf2.topAnchor.constraint(equalTo: ltf.bottomAnchor, constant: 8.0),
ltf2.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0),
ltf2.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 8.0),
ltf2.heightAnchor.constraint(equalToConstant: 60)
])
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.heightAnchor.constraint(equalToConstant:4000)
])
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let tag = textField.tag
let next = tag + 1
if next < self.textFields.count {
let textField = self.textFields[next]
textField.becomeFirstResponder()
self.scrollView.contentOffset = CGPoint(x: 0.0, y: textField.frame.origin.y - 8.0)
} else {
textField.resignFirstResponder()
}
return true
}
}
2 ответа
Проблема заключается в том, как вы устанавливаете теги в текстовом поле и помещаете их в массив.
ltf.textField.tag = 0
ltf2.textField.tag = 1
self.textFields.append(ltf2.textField)
self.textFields.append(ltf.textField)
Проблема в том, что теги не соответствуют порядку в массиве, так как массив в конечном итоге будет [ltf2.textField, ltf.textField]
, Я бы полностью пропустил использование тегов и просто использовал порядок в массиве.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let index = textFields.index(of: textField) {
let nextIndex = index + 1
let lastIndex = textFields.count - 1
if nextIndex <= lastIndex {
textFields[nextIndex].becomeFirstResponder()
}
}
return true
}
Вы можете зарезервировать память вместо того, чтобы объявлять массив для размещения текстовых файлов и попробовать что-то вроде этого
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
if let next = self.view.viewWithTag(textField.tag + 1) as? UITextField
{
next.becomeFirstResponder()
}
else
{
textField.resignFirstResponder()
}
return true
}