ios uitableview ios9

ios - scrollToRowAtIndexPath: atScrollPosition que hace que la vista de tabla "salte"



uitableview ios9 (5)

¡Prueba esto!

UITableViewRowAnimation rowAnimation = UITableViewRowAnimationTop; UITableViewScrollPosition scrollPosition = UITableViewScrollPositionTop; [self.tableView beginUpdates]; [messages addObject:msg]; [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:rowAnimation]; [self.tableView endUpdates]; [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:YES]; // Fixes the cell from blinking (because of the transform, when using translucent cells) [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

Mi aplicación tiene funcionalidad de chat y estoy introduciendo nuevos mensajes como este:

[self.tableView beginUpdates]; [messages addObject:msg]; [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:messages.count - 1 inSection:1]] withRowAnimation:UITableViewRowAnimationBottom]; [self.tableView endUpdates]; [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:messages.count - 1 inSection:1] atScrollPosition:UITableViewScrollPositionBottom animated:YES];

Sin embargo, mi vista de tabla "salta" de forma extraña cuando estoy agregando un nuevo mensaje (ya sea enviando y recibiendo, el resultado es el mismo en ambos):

¿Por qué estoy recibiendo este extraño "salto"?


Acabo de descubrir que en ios 11 este problema ya no existe. Así que ya no hay un salto de contenido cuando se agrega una fila a una vista de tabla y luego se desplaza hacia ella con scrollToRow(at:) .

Además, en ios 10 llamando a scrollToRowAtIndexPath con animated = false corrige el salto de contenido


Cambie UITableViewRowAnimationBottom a UITableViewRowAnimationNone y pruebe


OK, lo descubrí. Como usted dice, el problema tiene que ver con el tamaño automático de las celdas. Utilicé dos trucos para hacer que las cosas funcionen (mi código está en Swift, pero debería ser fácil de traducir al ObjC):

1) Espere a que termine la animación de la mesa antes de continuar con la acción. Esto se puede hacer adjuntando el código que actualiza la tabla dentro de un bloque entre CATransaction.begin() y CATransaction.commit() . Establecí el bloque de finalización en CATransaction, ese código se ejecutará una vez que la animación haya finalizado.

2) Forzar la vista de tabla para representar la celda antes de desplazarse a la parte inferior. Lo hago aumentando el contenido de la tabla contentOffset en una pequeña cantidad. Eso hace que la celda recién insertada se elimine de la cola y se calcule su altura. Una vez que se hace ese desplazamiento (espero a que termine de usar el método (1) anterior), finalmente llamo tableView.scrollToRowAtIndexPath .

Aquí está el código:

override func viewDidLoad() { super.viewDidLoad() // Use auto-sizing for rows tableView.estimatedRowHeight = 40 tableView.rowHeight = UITableViewAutomaticDimension tableView.dataSource = self } func chatManager(chatManager: ChatManager, didAddMessage message: ChatMessage) { messages.append(message) let indexPathToInsert = NSIndexPath(forRow: messages.count-1, inSection: 0) CATransaction.begin() CATransaction.setCompletionBlock({ () -> Void in // This block runs after the animations between CATransaction.begin // and CATransaction.commit are finished. self.scrollToLastMessage() }) tableView.beginUpdates() tableView.insertRowsAtIndexPaths([indexPathToInsert], withRowAnimation: .Bottom) tableView.endUpdates() CATransaction.commit() } func scrollToLastMessage() { let bottomRow = tableView.numberOfRowsInSection(0) - 1 let bottomMessageIndex = NSIndexPath(forRow: bottomRow, inSection: 0) guard messages.count > 0 else { return } CATransaction.begin() CATransaction.setCompletionBlock({ () -> Void in // Now we can scroll to the last row! self.tableView.scrollToRowAtIndexPath(bottomMessageIndex, atScrollPosition: .Bottom, animated: true) }) // scroll down by 1 point: this causes the newly added cell to be dequeued and rendered. let contentOffset = tableView.contentOffset.y let newContentOffset = CGPointMake(0, contentOffset + 1) tableView.setContentOffset(newContentOffset, animated: true) CATransaction.commit() }


Para Swift 3 y 4

para desplazarse hasta la parte inferior de la tabla. Ver automáticamente cuando se agrega un nuevo elemento en la vista de tabla solo en la función tableView.

tableView.scrollToRow (en: IndexPath, en: .bottom, animated: true)

por ejemplo, en mi caso solo tengo una sección, por lo que 0 se usa para la sección y tengo una lista de artículos de pedido, así que para el último índice utilizo orderItems.count - 1

tableView.scrollToRow (en: [0, orderItems.count - 1], en: .bottom, animated: true)