UITableView добавляет высоту клавиатуры к contentSize, когда клавиатура появляется на iOS11 - PullRequest
0 голосов
/ 26 февраля 2019

Я работаю над чатом, который должен работать на iOS 11 и 12. На iOS 12 все работает как положено.На iOS 11, однако, у меня проблема в том, что размер содержимого табличного представления увеличивается (без ячеек), как только появляется клавиатура.Величина дополнительной высоты совпадает с высотой клавиатуры.

Демо

Вот демонстрация с iOS 11 слева и iOS 12 справа.На iOS 12 все работает просто отлично.При появлении клавиатуры обратите внимание на нижнюю часть представления таблицы в iOS 11.

Table view content size iOS 11 Table view content size iOS 12

Просмотр / просмотрнастройка иерархии контроллера

- = Просмотр контроллера
+ = Просмотр

- UINavigationViewController
    - UIViewController // Controlling contentInsets, contentOffset of the tableView
        + UIView
        - UITableViewController
            + UITableView
        - UIViewController // Controlling the text input bar at the bottom
            + ... // Other views
            + UITextView

Ограничения макета

Якоря табличного представления равны якорям его суперпредставления,Так что на весь экран, игнорируя безопасную зону.Поэтому, когда появляется клавиатура, рамка не меняется, а нижний контент вставляется.

Подробнее

Я установил tableView.contentInsetAdjustmentBehavior = .never

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

@objc func handleKeyboardWillShowNotification(_ notification: NSNotification) {
    let frameEnd: CGRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue ?? .zero
    let keyboardHeight = frameEnd.height
    let contentHeight = tableView.contentSize.height
    let visibleTableViewHeight = tableView.frame.height - (tableView.contentInset.top + tableView.contentInset.bottom)
    let distanceToScroll = (keyboardHeight - view.safeAreaInsets.bottom)
    var y: CGFloat = 0
    if contentHeight > visibleTableViewHeight {
        y = tableView.contentOffset.y + distanceToScroll
    } else {
        let diff = visibleTableViewHeight - contentHeight
        let positionAtKeyboard = distanceToScroll - tableView.contentInset.top - diff
        y = positionAtKeyboard < tableView.contentInset.top ? -tableView.contentInset.top : positionAtKeyboard
    }
    let contentOffset = CGPoint(x: 0, y: y)
    tableView.contentInset.bottom = keyboardHeight + inputBar.frame.height
    tableView.scrollIndicatorInsets = tableView.contentInset
    tableView.setContentOffset(contentOffset, animated: false)
}

Я также пробовал это на разных размерах экрана, и он всегда добавляет к contentSize сумму, которая точно соответствуетвысота клавиатуры.

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

Вы можете использовать следующий код для скрытия и отображения клавиатуры.

// Показать клавиатуру.

@objc func keyboardWillAppear(_ notification: NSNotification) {
    if let newFrame = (notification.userInfo?[ UIResponder.keyboardFrameEndUserInfoKey ] as? NSValue)?.cgRectValue {
        if self.tableView.contentInset.bottom == 0 {
            let insets: UIEdgeInsets = UIEdgeInsets( top: 0, left: 0, bottom: newFrame.height, right: 0 )
            self.tableView.contentInset = insets
            self.tableView.scrollIndicatorInsets = insets
            UIView.animate(withDuration: 0.1) {
                self.view.layoutIfNeeded()
            }
        }
    }
}

// Скрыть клавиатуру.

@objc func keyboardWillDisappear(_ notification: NSNotification) {
    if self.tableView.contentInset.bottom != 0 {
        self.tableView.contentInset = UIEdgeInsets( top: 0, left: 0, bottom: 0, right: 0 )
        self.tableView.scrollIndicatorInsets = UIEdgeInsets( top: 0, left: 0, bottom: 0, right: 0 )
        UIView.animate(withDuration: 0.1) {
            self.view.layoutIfNeeded()
        }
    }
}

Это работа для меня.

0 голосов
/ 01 марта 2019

Обходной путь

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

Я мог бы обойти эту проблему, изменив ограничения и не устанавливая нижние вставки.Изначально нижнее ограничение табличного представления было установлено в нижнюю часть супер-представления (в основном, нижнюю часть экрана).Поэтому, когда появилась клавиатура, я изменил не рамку табличного представления, а нижнюю вставку.По-видимому, это не сработало должным образом.

Теперь я установил нижнее ограничение табличного представления на верхнюю часть входного представления (черная полоса), а нижняя вставка на ноль.Поскольку представление ввода перемещается вверх, когда появляется клавиатура, оно меняет рамку представления таблицы, а нижняя вставка остается нулевой.Я все еще устанавливаю смещение содержимого, потому что мне нужно определенное поведение в разных ситуациях, но это все.

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

0 голосов
/ 26 февраля 2019

Прежде всего вам не нужно выполнять ненужные вычисления. Просто рассчитайте высоту клавиатуры и переместите ее вверх ногами.

Swift Версия:

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height + 10, right: 0)
        UIView.animate(withDuration: 0.25) {
            self.tableView.layoutIfNeeded()
            self.view.layoutIfNeeded()
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {

    self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    UIView.animate(withDuration: 0.5) {
        self.tableView.layoutIfNeeded()
        self.view.layoutIfNeeded()
    }
}

Версия Objecttive-C:

- (void)keyboardWillShow:(NSNotification *)notification
{
    NSDictionary *keyInfo = [notification userInfo];
    CGRect keyboardFrame = [[keyInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardFrame.size.height + 10, 0);

    [UIView animateWithDuration:0.2 animations:^{
        [self.tableView layoutIfNeeded];
        [self.view layoutIfNeeded];
    } completion:nil];
}

- (void) keyboardWillHide:  (NSNotification *) notification
{
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    [UIView animateWithDuration:0.2 animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
}

Дайте мне знать, если обнаружите какие-либо трудности.Это работает для меня очень хорошо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...