В моем проекте iOS у меня есть контроллер представления с парой текстовых полей. Чтобы гарантировать, что элементы управления остаются видимыми, когда пользователь вводит текст, я использую следующий код для перемещения содержимого и освобождения места для клавиатуры:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
@objc func keyboardWillShow(notification: NSNotification) {
dPrint(tag: "Safe Area", message: "keyboardWillShow()")
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if activeField != nil {
var activeFieldBottomDistance: CGFloat = view.frame.size.height - ... // calculation of position omitted here
let yOffset: CGFloat = activeFieldBottomDistance
- keyboardSize.height
- view.frame.origin.y
if yOffset + view.frame.origin.y < 0 {
moveViewForKeyboard(offset: yOffset)
}
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
dPrint(tag: "Safe Area", message: "keyboardWillHide()")
let yOffset: CGFloat = -view.frame.origin.y
moveViewForKeyboard(offset: yOffset)
}
func moveViewForKeyboard(offset: CGFloat!) {
let duration = 0.3
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(duration)
view.frame = view.frame.offsetBy(dx: 0, dy: offset)
UIView.commitAnimations()
view.setNeedsLayout()
view.layoutIfNeeded()
}
Макет выглядит следующим образом (с текстовыми представлениями внутри стекового представления):
![Layout](https://i.stack.imgur.com/2LOo4.png)
Моя проблема в том, что при перемещении корневого представления вверх, чтобы освободить место для клавиатуры, поля безопасной области теряются. Например. при использовании его в альбомной ориентации и при появлении клавиатуры содержимое расширяется по горизонтали, а когда клавиатура снова скрывается, содержимое возвращается в пределы безопасной области.
Затем следующий код выдает следующий результат:
@available(iOS 11.0, *)
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
dPrint(tag: "Safe Area", message: "saveAreaInsetsDidChange")
dPrint(tag: "Safe Area", message: "top: " + String(describing: view.safeAreaInsets.top))
dPrint(tag: "Safe Area", message: "right: " + String(describing: view.safeAreaInsets.right))
dPrint(tag: "Safe Area", message: "bottom: " + String(describing: view.safeAreaInsets.bottom))
dPrint(tag: "Safe Area", message: "left: " + String(describing: view.safeAreaInsets.left))
}
Safe Area saveAreaInsetsDidChange
Safe Area top: 0.0
Safe Area right: 44.0
Safe Area bottom: 21.0
Safe Area left: 44.0
Safe Area keyboardWillShow()
Safe Area saveAreaInsetsDidChange
Safe Area top: 0.0
Safe Area right: 0.0
Safe Area bottom: 0.0
Safe Area left: 0.0
Safe Area keyboardWillHide()
Safe Area saveAreaInsetsDidChange
Safe Area top: 0.0
Safe Area right: 44.0
Safe Area bottom: 21.0
Safe Area left: 44.0
Как я могу переместить контент, чтобы он оставался в безопасной зоне и чтобы он работал также на старых устройствах, начиная с iOS9.
(Одна из опций, которые я пробовал, - создать дополнительный слой вида под корневым видом и переместить его. Это не сработало, потому что содержимое, представленное модально, как диалоговое окно, центрируется по вертикали. корневое представление не позволяет смещать содержимое.)