Estoy trabajando en un chat que debería funcionar en iOS 11 y 12. En iOS 12 todo funciona como se esperaba. En iOS 11, sin embargo, tengo el problema de que el tamaño del contenido de la vista de tabla aumenta (sin celdas) tan pronto como aparece el teclado. La cantidad de altura adicional coincide con la altura del teclado.
Aquí hay una demostración con iOS 11 a la izquierda y iOS 12 a la derecha. En iOS 12 todo funciona bien. Preste atención a la parte inferior de la vista de tabla en iOS 11 cuando apareció el teclado.
- = Ver controlador
+ = Ver
- UINavigationViewController - UIViewController // Controlling contentInsets, contentOffset of the tableView + UIView - UITableViewController + UITableView - UIViewController // Controlling the text input bar at the bottom + ... // Other views + UITextViewLos anclajes de la vista de tabla son iguales a los anclajes de su supervista. Así que pantalla completa, ignorando el área segura. Entonces, cuando aparece el teclado, el marco no cambia, pero el contenido inferior se inserta.
Configuré tableView.contentInsetAdjustmentBehavior = .never
Así es como calculo las inserciones y el desplazamiento de la vista de la tabla cuando aparece el teclado. Es complejo porque hay varios escenarios donde debería haber un comportamiento diferente. Hay un cálculo complejo similar cuando desaparece el teclado y cuando cambia la altura de la entrada de texto. Siempre quiero desplazar la vista de la tabla hacia arriba o hacia abajo según los cambios en el marco de la vista.
@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) } También probé esto en diferentes tamaños de pantalla y siempre agrega una cantidad al tamaño del contentSize que coincide exactamente con la altura del teclado.
Puede usar el siguiente código para ocultar y mostrar el teclado.
//Mostrar teclado.
@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() } } } }//Ocultar teclado.
@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() } } }Esto es trabajo para mí.
En primer lugar, no tiene que hacer cálculos innecesarios. Simplemente calcule la altura del teclado y mueva el teclado hacia arriba.
Versión rápida:
@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() } }Versión de Objective-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]; }Avísame si encuentras alguna dificultad. esto me funciona muy bien
Esto no responde específicamente a la pregunta original, pero podría ser una solución para aquellos que no tienen un teclado translúcido y una vista de entrada.
Podría solucionar este problema cambiando las restricciones y no configurando las inserciones inferiores. Inicialmente, la restricción inferior de la vista de tabla se estableció en la parte inferior de la supervista (básicamente, en la parte inferior de la pantalla). Entonces, cuando apareció el teclado, no cambié el marco de la vista de tabla, sino el recuadro inferior. Esto aparentemente no funcionó correctamente.
Ahora configuré la restricción inferior de la vista de tabla en la parte superior de la vista de entrada (barra negra) y el recuadro inferior en cero. Dado que la vista de entrada se mueve hacia arriba cuando aparece el teclado, cambia el marco de la vista de tabla y el recuadro inferior permanece en cero. Todavía configuro la compensación de contenido, porque necesito un comportamiento específico en diferentes situaciones, pero eso es todo.
Esto solo funciona en mi situación, porque no tengo una barra de entrada translúcida ni un teclado y no necesito mostrar contenido borroso detrás.