Изменение размера экрана при появлении клавиатуры

Я создаю приложение чата. Я должен переместить текстовое поле, когда появляется клавиатура. Я делаю это с помощью следующего кода:

func keyboardWillShow(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        if let keyboardSize =  (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            kbHeight = keyboardSize.height
            self.animateTextField(true)
        }
    }
}
func keyboardWillHide(notification: NSNotification) {
    self.animateTextField(false)
}

func animateTextField(up: Bool) {
    var movement = (up ? -kbHeight : kbHeight)

    UIView.animateWithDuration(0.3, animations: {
        self.view.frame = CGRectOffset(self.view.frame, 0, movement)
    })
}

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

Вот скриншоты До и После появляется клавиатура:

Я использую автоматическую разметку.

Как я могу решить эту проблему?

Ответ 1

Вы можете создать выход из нижнего ограничения макета в виде таблицы.

Затем просто используйте этот код:

func keyboardWillShow(sender: NSNotification) {
    let info = sender.userInfo!
    var keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
    bottomConstraint.constant = keyboardSize - bottomLayoutGuide.length

    let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue

    UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() }
}

func keyboardWillHide(sender: NSNotification) {
    let info = sender.userInfo!
    let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
    bottomConstraint.constant = 0

    UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() }
}

Если у вас возникли проблемы с созданием нижнего ограничения:

В раскадровке

  • Выберите строку поиска.
  • На углу в правом нижнем углу вы увидите 3 значка. Нажмите средний, похожий на |-[]-|.
  • В верхней части этого всплывающего окна есть 4 окна. Введите 0 в нижний.
  • Создан Constraint!

Теперь вы можете перетащить его в свой контроллер просмотра и добавить его как выход.

Другим решением является установка tableView.contentInset.bottom. Но я этого не делал раньше. Если вы предпочитаете это, я могу попытаться объяснить это.

Использование вставки:

func keyboardWillShow(sender: NSNotification) {
    let info = sender.userInfo!
    let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height

    tableView.contentInset.bottom = keyboardSize
}

func keyboardWillHide(sender: NSNotification) {
    tableView.contentInset.bottom = 0
}

Вы можете попробовать этот код для установки вставки. Я еще не пробовал это сам, но это должно быть что-то вроде этого.

EDIT: Изменена продолжительность с помощью nacho4d

Ответ 2

ОБНОВЛЕНИЕ 2017/2019

Есть только один способ правильно справиться с этим беспорядком в iOS.

1) Вставьте KUIViewController в свой проект,

2) Создайте ограничение, которое просто находится в "нижней части вашего контента". Обсуждается ниже.

3) Перетащите идентификатор ограничения на bottomConstraintForKeyboard

KUIViewController будет автоматически и правильно изменять размер вашего контента в любое время.

Вопрос решен.

Так "какой вид вы должны изменить размер?"

Вы не можете использовать .view. Потому что вы не можете изменить размер .view в iOS!

Просто сделайте UIView с именем "держатель". Он сидит внутри .view.

Положите все свое в держателе.

Держатель, конечно, будет иметь четыре простых ограничения сверху/снизу/слева/справа до .view.

Это нижнее ограничение для "держателя" действительно bottomConstraintForKeyboard.

Вы сделали Отправьте счет клиенту и пейте. Больше нечего делать.

Проблема 2... щелкнув "фон", чтобы очистить клавиатуру

Обычно в современном UX, если вы нажмете "выкл" - так: подальше от каких-либо кнопок, полей ввода - он должен отклонить клавиатуру.

Класс KUIViewController полностью автоматизирует это. Ничего не делать.

class KUIViewController: UIViewController {

    // KBaseVC is the KEYBOARD variant BaseVC. more on this later

    @IBOutlet var bottomConstraintForKeyboard: NSLayoutConstraint!

    @objc func keyboardWillShow(sender: NSNotification) {
        let i = sender.userInfo!
        let k = (i[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
        bottomConstraintForKeyboard.constant = k - bottomLayoutGuide.length
        let s: TimeInterval = (i[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
        UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
    }

    @objc func keyboardWillHide(sender: NSNotification) {
        let info = sender.userInfo!
        let s: TimeInterval = (info[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
        bottomConstraintForKeyboard.constant = 0
        UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
    }

    @objc func clearKeyboard() {
        view.endEditing(true)
    }

    func keyboardNotifications() {
        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 viewDidLoad() {
        super.viewDidLoad()
        keyboardNotifications()
        let t = UITapGestureRecognizer(target: self, action: #selector(clearKeyboard))
        view.addGestureRecognizer(t)
        t.cancelsTouchesInView = false
    }
}

Ты...

Используйте KUIViewController везде, где может появиться клавиатура.

class AddCustomer: KUIViewController, SomeProtocol {

class CustomerPicker: KUIViewController {

На этих экранах абсолютно все теперь полностью автоматизировано. Конец истории.


* Незначительная сноска - фоновые щелчки правильно отклоняют клавиатуру. Это включает в себя клики, которые попадают на ваш контент. Это правильное поведение Apple. Любое необычное изменение потребовало бы специального программирования.

Ответ 3

Из сообщения @Fattie:

Детали - (к сожалению) клики по вашему контенту также отклонят клавиатуру. (Они оба получают событие.) Однако это почти всегда правильное поведение; попробуйте. Нет разумного избежать этого, поэтому забудьте об этом и идите с потоком Apple.

Это можно решить, выполнив следующий метод UIGestureRecognizerDelegate:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        return !(touch.view?.isKind(of: UIControl.self) ?? true)
    }

Таким образом, если пользователь коснется любого UIControl (UIButton, UITextField и т.д.), распознаватель жестов не вызовет метод clearKeyboard().

Чтобы это сработало, запомните подкласс UIGestureRecognizerDelegate либо в определении класса, либо с расширением. Затем в viewDidLoad() вы должны назначить делегат распознавателя жестов как self.


Готов к копированию и вставке кода:

// 1. Subclass UIGestureRecognizerDelegate
class KUIViewController: UIViewController, UIGestureRecognizerDelegate {

@IBOutlet var bottomConstraintForKeyboard: NSLayoutConstraint!

func keyboardWillShow(sender: NSNotification) {
    let i = sender.userInfo!
    let k = (i[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
    bottomConstraintForKeyboard.constant = k - bottomLayoutGuide.length
    let s: TimeInterval = (i[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
    UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}

func keyboardWillHide(sender: NSNotification) {
    let info = sender.userInfo!
    let s: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
    bottomConstraintForKeyboard.constant = 0
    UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}

func keyboardNotifications() {
    NotificationCenter.default.addObserver(self,
        selector: #selector(keyboardWillShow),
        name: Notification.Name.UIKeyboardWillShow,
        object: nil)
    NotificationCenter.default.addObserver(self,
        selector: #selector(keyboardWillHide),
        name: Notification.Name.UIKeyboardWillHide,
        object: nil)
}

func clearKeyboard() {
    view.endEditing(true)
}

override func viewDidLoad() {
    super.viewDidLoad()
    keyboardNotifications()
    let t = UITapGestureRecognizer(target: self, action: #selector(clearKeyboard))
    view.addGestureRecognizer(t)
    t.cancelsTouchesInView = false

    // 2. Set the gesture recognizer delegate as self
    t.delegate = self
}

// 3. Implement this method from UIGestureRecognizerDelegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return !(touch.view?.isKind(of: UIControl.self) ?? true)
}
}

Ответ 4

если вы не хотите драться с этим сами, вы можете найти TPKeyboardAvoiding framework

Просто следуйте инструкциям по установке, то есть перетащите соответствующие файлы .h/.m в свой проект, а затем сделайте ScrollView/TableView подклассом, как показано ниже:

Custom Class