Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

686
Visualizações
UITableView adds height of keyboard to contentSize when the keyboard appears on iOS11

I'm working on a chat that should work on iOS 11 and 12. On iOS 12 everything works as expected. On iOS 11, however, I have the problem that the table view content size increases (no cells) as soon as the keyboard appears. The amount of extra height matches with the keyboard height.

Demo

Here is a demo with iOS 11 on the left and iOS 12 on the right. On iOS 12 everything works just fine. Put attention to the bottom of the table view on iOS 11 when the keyboard appeared.

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

View/View controller hierarchy setup

- = View controller
+ = View

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

Layout Constraints

The table view's anchors are equal to its superview's anchors. So fullscreen, ignoring safe area. So when the keyboard appears the frame doesn't change, but the bottom content insets.

More Details

I've set tableView.contentInsetAdjustmentBehavior = .never

This is how I calculate the insets and offset of the table view when the keyboard appears. It's complex because there are several scenarios where there should be different behavior. There's a similar complex calculation when the keyboard disappears, and when the height of the text input changes. I always want to scroll the table view up or down according to view frame changes.

@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)
}

I also have tried this on different screen sizes and it always adds an amount to the contentSize that matches exactly the height of the keyboard.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

You can use following code for keyboard hide and show.

//Show keyboard.

@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()
            }
        }
    }
}

//Hide keyboard.

@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()
        }
    }
}

This is work for me.

over 4 years ago · Santiago Trujillo Relatório

0

First of all you don't have to do unnecessary calculation Simply calculate the keyboard height, and move the keyboard upside.

Swift Version:

@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 Version:

- (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];
}

Let me know If you find any difficulties. This works for me very well

over 4 years ago · Santiago Trujillo Relatório

0

Workaround

This is not specifically answering the original question, but might be a solution for those who don't have a translucent keyboard and input view.

I could get around this problem by changing the constraints and not setting the bottom insets. Initially the bottom constraint of the table view was set to the bottom of the super view (bottom of the screen, basically). So when the keyboard appeared, I didn't change the table view's frame, but the bottom inset. This apparently didn't work properly.

Now I've set the bottom constraint of the table view to the top of the input view (black bar) and the bottom inset to zero. Since the input view moves up when the keyboard appears, it changes the frame of the table view and the bottom inset remains zero. I still set the content offset, because I need specific behavior in different situations, but that's it.

This only works in my situation, because I neither have a translucent input bar nor keyboard and don't need to show blurry content behind it.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda