Вставки безопасной зоны исчезают при перемещении вида - PullRequest
1 голос
/ 31 мая 2019

В моем проекте 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

Моя проблема в том, что при перемещении корневого представления вверх, чтобы освободить место для клавиатуры, поля безопасной области теряются. Например. при использовании его в альбомной ориентации и при появлении клавиатуры содержимое расширяется по горизонтали, а когда клавиатура снова скрывается, содержимое возвращается в пределы безопасной области.

Затем следующий код выдает следующий результат:

@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.

(Одна из опций, которые я пробовал, - создать дополнительный слой вида под корневым видом и переместить его. Это не сработало, потому что содержимое, представленное модально, как диалоговое окно, центрируется по вертикали. корневое представление не позволяет смещать содержимое.)

1 Ответ

1 голос
/ 08 июня 2019

Для этого вы можете использовать библиотеку UnderKeyboard .

Поэтому я настоятельно рекомендую использовать UIScrollView для перемещения вашего контента, когда клавиатура открыта.Следуйте этому руководству .

Или используйте нижнее ограничение AutoLayout для заполнения нижней части и анимируйте изменение его константы.

Пример:

@IBOutlet var bottomConstraint: NSLayoutConstraint!

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillHideNotification, object: nil)
}

func animateWithKeyboard(notification: NSNotification) {

    let userInfo = notification.userInfo!
    let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
    let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! Double
    let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UInt
    let moveUp = (notification.name == UIKeyboardWillShowNotification)

    bottomConstraint.constant = moveUp ? -keyboardHeight : 0

    let options = UIViewAnimationOptions(rawValue: curve << 16)
    UIView.animateWithDuration(duration, delay: 0, options: options, animations: {
        self.view.layoutIfNeeded()
    },
    completion: nil)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...