Tener un reloadData para una animación UITableView cuando se cambia

Tengo una UITableView que tiene dos modos. Cuando cambiamos de modo, tengo un número diferente de secciones y celdas por sección. Idealmente, haría una animación genial cuando la mesa crezca o se encoja.

Aquí está el código que probé, pero no hace nada:

CGContextRef context = UIGraphicsGetCurrentContext(); [UIView beginAnimations:nil context:context]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:0.5]; [self.tableView reloadData]; [UIView commitAnimations]; 

¿Alguna idea de cómo podría hacer esto?

En realidad, es muy simple:

 [_tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 

De la documentación :

Llamar a este método hace que la vista de tabla solicite a su fuente de datos nuevas celdas para las secciones especificadas. La vista de tabla anima la inserción de nuevas celdas mientras anima las celdas antiguas.

Es posible que desee usar:

C objective

 [UIView transitionWithView: self.tableView duration: 0.35f options: UIViewAnimationOptionTransitionCrossDissolve animations: ^(void) { [self.tableView reloadData]; } completion: nil]; 

Rápido

 UIView.transitionWithView(tableView, duration: 0.35, options: .TransitionCrossDissolve, animations: { () -> Void in self.tableView.reloadData() }, completion: nil); 

Swift 3

 UIView.transition(with: tableView, duration: 0.35, options: .transitionCrossDissolve, animations: { self.tableView.reloadData() }) // left out the unnecessary syntax in the completion block and the optional completion parameter 

Sin molestias. :RE

También puede usar cualquiera de UIViewAnimationOptionTransitions que desee para efectos más fríos:

  • TransitionNone
  • TransitionFlipFromLeft
  • TransitionFlipFromRight
  • TransitionCurlUp
  • TransitionCurlDown
  • TransitionCrossDissolve
  • TransitionFlipFromTop
  • TransitionFlipFromBottom

Tener más libertad usando la clase CATransition .

No se limita al desvanecimiento, sino que también puede hacer movimientos …


Por ejemplo:

(no te olvides de importar QuartzCore )

 CATransition *transition = [CATransition animation]; transition.type = kCATransitionPush; transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; transition.fillMode = kCAFillModeForwards; transition.duration = 0.5; transition.subtype = kCATransitionFromBottom; [[self.tableView layer] addAnimation:transition forKey:@"UITableViewReloadDataAnimationKey"]; 

Cambie el type para que coincida con sus necesidades, como kCATransitionFade etc.

Implementación en Swift:

 let transition = CATransition() transition.type = kCATransitionPush transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) transition.fillMode = kCAFillModeForwards transition.duration = 0.5 transition.subtype = kCATransitionFromTop self.tableView.layer.addAnimation(transition, forKey: "UITableViewReloadDataAnimationKey") // Update your data source here self.tableView.reloadData() 

Referencia para CATransition

Creo que puedes actualizar tu estructura de datos, entonces:

 [tableView beginUpdates]; [tableView deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]; [tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]; [tableView endUpdates]; 

Además, “withRowAnimation” no es exactamente un booleano, sino un estilo de animación:

 UITableViewRowAnimationFade, UITableViewRowAnimationRight, UITableViewRowAnimationLeft, UITableViewRowAnimationTop, UITableViewRowAnimationBottom, UITableViewRowAnimationNone, UITableViewRowAnimationMiddle 

Todas estas respuestas asumen que está utilizando una UITableView con solo 1 sección.

Para manejar con precisión las situaciones en las que tiene más de una sección, use:

 NSRange range = NSMakeRange(0, myTableView.numberOfSections); NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range]; [myTableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic]; 

(Nota: ¡debes asegurarte de tener más de 0 secciones!)

Otra cosa a tener en cuenta es que puede encontrarse con una NSInternalInconsistencyException si intenta actualizar simultáneamente su fuente de datos con este código. Si este es el caso, puede usar una lógica similar a esta:

 int sectionNumber = 0; //Note that your section may be different int nextIndex = [currentItems count]; //starting index of newly added items [myTableView beginUpdates]; for (NSObject *item in itemsToAdd) { //Add the item to the data source [currentItems addObject:item]; //Add the item to the table view NSIndexPath *path = [NSIndexPath indexPathForRow:nextIndex++ inSection:sectionNumber]; [myTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationAutomatic]; } [myTableView endUpdates]; 

La forma de abordar esto es decirle a tableView que elimine y agregue filas y secciones con el

insertRowsAtIndexPaths:withRowAnimation: deleteRowsAtIndexPaths:withRowAnimation: insertSections:withRowAnimation: y deleteSections:withRowAnimation:

métodos de UITableView. Cuando llame a estos métodos, la tabla animará la entrada / salida de los elementos solicitados, luego llamará a reloadData para que pueda actualizar el estado después de esta animación. Esta parte es importante: si anulas todo pero no cambias los datos devueltos por dataSource de la tabla, las filas volverán a aparecer una vez completada la animación.

Por lo tanto, el flujo de su aplicación sería:

[self setTableIsInSecondState:YES];

[myTable deleteSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:YES]];

Siempre que los métodos dataSource de su tabla devuelvan el nuevo conjunto correcto de secciones y filas al marcar [self tableIsInSecondState] (o lo que sea), esto logrará el efecto que está buscando.

No puedo comentar la respuesta principal, pero una implementación rápida sería:

 self.tableView.reloadSections([0], with: UITableViewRowAnimation.fade) 

podría incluir tantas secciones como desee actualizar en el primer argumento para reloadSections.

Otras animaciones disponibles en los documentos: https://developer.apple.com/reference/uikit/uitableviewrowanimation

fade La fila o filas insertadas o eliminadas se desvanecen dentro o fuera de la vista de tabla.

derecha La fila o filas insertadas se deslizan desde la derecha; la fila o las filas eliminadas se deslizan hacia la derecha.

left La fila o filas insertadas se deslizan desde la izquierda; la fila o filas eliminadas se deslizan hacia la izquierda.

arriba La fila o filas insertadas se deslizan desde la parte superior; la fila o filas eliminadas se deslizan hacia la parte superior.

abajo La fila o filas insertadas se deslizan desde la parte inferior; la fila o las filas eliminadas se deslizan hacia la parte inferior.

caso ninguno Las filas insertadas o eliminadas usan las animaciones predeterminadas.

medio La vista de tabla intenta mantener las celdas nuevas y viejas centradas en el espacio que ocupan u ocuparán. Disponible en iPhone 3.2.

automático La vista de tabla elige un estilo de animación apropiado para usted. (Introducido en iOS 5.0)

Implementación de Swift:

 let range = NSMakeRange(0, self.tableView!.numberOfSections()) let indexSet = NSIndexSet(indexesInRange: range) self.tableView!.reloadSections(indexSet, withRowAnimation: UITableViewRowAnimation.Automatic) 

Swift 4 versión para @dmarnel respuesta:

 tableView.reloadSections(IndexSet(integer: 0), with: .automatic) 

En mi caso, quería agregar 10 filas más a la vista de tabla (para una funcionalidad de “mostrar más resultados”) e hice lo siguiente:

  NSInteger tempNumber = self.numberOfRows; self.numberOfRows += 10; NSMutableArray *arrayOfIndexPaths = [[NSMutableArray alloc] init]; for (NSInteger i = tempNumber; i < self.numberOfRows; i++) { [arrayOfIndexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]]; } [self.tableView beginUpdates]; [self.tableView insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; 

En la mayoría de los casos, en lugar de "self.numberOfRows", normalmente usaría el recuento de la matriz de objetos para la vista de tabla. Por lo tanto, para asegurarse de que esta solución funcione bien para usted, "arrayOfIndexPaths" debe ser una matriz precisa de las rutas de índice de las filas que se insertan. Si la fila existe para cualquiera de estas rutas de índice, el código puede bloquearse, por lo que debe usar el método "reloadRowsAtIndexPaths: withRowAnimation:" para las rutas de índice para evitar lockings.

Si desea agregar sus propias animaciones personalizadas a las celdas UITableView, use

 [theTableView reloadData]; [theTableView layoutSubviews]; NSArray* visibleViews = [theTableView visibleCells]; 

para obtener una matriz de celdas visibles A continuación, agregue cualquier animación personalizada a cada celda.

Echa un vistazo a esta idea que publiqué para una animación de celular personalizada sin problemas. https://gist.github.com/floprr/1b7a58e4a18449d962bd

Animar sin reloadData () en Swift se puede hacer así (a partir de la versión 2.2):

 tableview.beginUpdates() var indexPathsToDeleteForAnimation: [NSIndexPath] = [] var numOfCellsToRemove = ArrayOfItemsToRemove ?? 0 // Do your work here while numOfCellsToRemove > 0 { // ...or here, if you need to add/remove the same amount of objects to/from somewhere indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0)) numOfCellsToRemove -= 1 } tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right) tableview.endUpdates() 

en caso de que necesite llamar a reloadData () después de que termine la animación, puede aceptar los cambios en CATransaction de esta manera:

 CATransaction.begin() CATransaction.setCompletionBlock({() in self.tableview.reloadData() }) tableview.beginUpdates() var indexPathsToDeleteForAnimation: [NSIndexPath] = [] var numOfCellsToRemove = ArrayOfItemsToRemove.count ?? 0 // Do your work here while numOfCellsToRemove > 0 { // ...or here, if you need to add/remove the same amount of objects to/from somewhere indexPathsToDeleteForAnimation.append(NSIndexPath(forRow: selectedCellIndex+numOfCellsToRemove, inSection: 0)) numOfCellsToRemove -= 1 } tableview.deleteRowsAtIndexPaths(indexPathsToDeleteForAnimation, withRowAnimation: UITableViewRowAnimation.Right) tableview.endUpdates() CATransaction.commit() 

La lógica se muestra para el caso cuando elimina filas, pero la misma idea también funciona para agregar filas. También puede cambiar la animación a UITableViewRowAnimation.Left para que quede nítida o elegir de la lista de otras animaciones disponibles.

 CATransition *animation = [CATransition animation]; animation.duration = .3; [animation setType:kCATransitionPush]; [animation setSubtype:kCATransitionFromLeft]; [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [animation setDuration:.3]; [[_elementTableView layer] addAnimation:animation forKey:@"UITableViewReloadDataAnimationKey"]; [tableView reloadData];