2010-09-30 20 views
80

¿Hay alguna forma de especificar la duración de las animaciones de fila UITableView o de obtener una devolución de llamada cuando finaliza la animación?Duración de animación de fila UITableView y devolución de llamada de finalización

Lo que me gustaría hacer es actualizar los indicadores de desplazamiento una vez que finalice la animación. Hacer el flash antes no hace nada. Hasta ahora, la solución que tengo es para retrasar medio segundo (que parece ser la duración de la animación por defecto), es decir:

[self.tableView insertRowsAtIndexPaths:newRows 
         withRowAnimation:UITableViewRowAnimationFade]; 
[self.tableView performSelector:@selector(flashScrollIndicators) 
        withObject:nil 
        afterDelay:0.5]; 
+0

No he probado a mí mismo, pero tal vez esto podría hacerlo, con un manejo ruta del índice: '- (void) tableView: (UITableView *) tableView didEndDisplayingCell: celda (UITableViewCell *) forRowAtIndexPath: (NSIndexPath *) indexPath' – Kalle

Respuesta

-8

usted podría tratar de envolver el insertRowsAtIndexPath en una transacción

- (void)beginUpdates 
- (void)endUpdates 

, luego haz el flash después.

+0

Consulte la respuesta de karwag anterior.Debe resolver el problema de lo que cuenta como "después". – JLundell

169

Acabo de encontrar esto. He aquí cómo hacerlo:

Objective-C

[CATransaction begin]; 
[tableView beginUpdates]; 
[CATransaction setCompletionBlock: ^{ 
    // Code to be executed upon completion 
}]; 
[tableView insertRowsAtIndexPaths: indexPaths 
       withRowAnimation: UITableViewRowAnimationAutomatic]; 
[tableView endUpdates]; 
[CATransaction commit]; 

Swift

CATransaction.begin() 
tableView.beginUpdates() 
CATransaction.setCompletionBlock { 
    // Code to be executed upon completion 
} 
tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top) 
tableView.endUpdates() 
CATransaction.commit() 
+0

No lo he probado pero parece prometedor. –

+0

He intentado esto (justo ahora) y parece funcionar bien. Bonificación: esto implica que también puede usar CATransaction para establecer la duración de la animación y la función de temporización. ¡Bonito! – JLundell

+0

En una mayor experimentación, el comportamiento de este mecanismo en este contexto parece errático en el mejor de los casos. Tenga en cuenta también que la documentación dice que se aplica solo a las animaciones agregadas después de la llamada. – JLundell

-5

Anulación tableView -insertRowsAtIndexPaths: e implementar la inserción personalizados/(o la supresión con su propio método) animación que desee. No lo intenté yo solo sin embargo.

37

Ampliando en karwag's fine answer, tenga en cuenta que en iOS 7, el entorno de la CATransaction con una animación UIView ofrece control de la duración de la animación de la tabla.

[UIView beginAnimations:@"myAnimationId" context:nil]; 

[UIView setAnimationDuration:10.0]; // Set duration here 

[CATransaction begin]; 
[CATransaction setCompletionBlock:^{ 
    NSLog(@"Complete!"); 
}]; 

[myTable beginUpdates]; 
// my table changes 
[myTable endUpdates]; 

[CATransaction commit]; 
[UIView commitAnimations]; 

La duración de la animación UIView no tiene ningún efecto en iOS 6. Tal animaciones iOS 7 de mesa se implementan de forma diferente, a nivel UIView.

+0

Esto funcionó muy bien para yo en ios 7 –

+0

La duración de la animación parece ser ignorada. – Dustin

23

Acortar Brent's fine answer, por lo menos durante 7 IOS se puede envolver todo esto concisamente en una [UIView animateWithDuration: retardo: Opciones: animaciones: finalización:] llamar:

[UIView animateWithDuration:10 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 
    [self.tableView beginUpdates]; 
    [self.tableView endUpdates]; 
} completion:^(BOOL finished) { 
    // completion code 
}]; 

sin embargo, me parece que no puede anula la curva de animación predeterminada de cualquier otra cosa que no sea EaseInOut.

+2

Al hacer una fila insertar de esta manera, o el camino de @ Brent, aunque se respeta la duración, la UITableViewRowAnimation no parece respetarse y siempre parece animarse de arriba hacia abajo, incluso cuando especifico, por ejemplo, UITableViewRowAnimationLeft. Pruebas en iOS 8.4: ¿Alguien tiene una solución? – Danny

5

Para mí lo necesitaba para una collectionView. He hecho una simple extensión de resolver esto:

extension UICollectionView { 

    func reloadSections(sections: NSIndexSet, completion:() -> Void){ 
     CATransaction.begin() 
     CATransaction.setCompletionBlock(completion) 

     self.reloadSections(sections) 

     CATransaction.commit() 
    } 

} 
19

Aquí hay una versión de Swift karwag's answer

CATransaction.begin() 
    tableView.beginUpdates() 
    CATransaction.setCompletionBlock {() -> Void in 
     // your code here 
    } 
    tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top) 
    tableView.endUpdates() 
    CATransaction.commit() 
14

Eso es un infierno de un truco útil! Escribí una extensión UITableView para evitar escribir cosas de CATransaction todo el tiempo.

import UIKit 

extension UITableView { 

    /// Perform a series of method calls that insert, delete, or select rows and sections of the table view. 
    /// This is equivalent to a beginUpdates()/endUpdates() sequence, 
    /// with a completion closure when the animation is finished. 
    /// Parameter update: the update operation to perform on the tableView. 
    /// Parameter completion: the completion closure to be executed when the animation is completed. 

    func performUpdate(_ update:()->Void, completion: (()->Void)?) { 

     CATransaction.begin() 
     CATransaction.setCompletionBlock(completion) 

     // Table View update on row/section 
     beginUpdates() 
     update() 
     endUpdates() 

     CATransaction.commit() 
    } 

} 

Esto se utiliza de esta manera:

// Insert in the tableView the section we just added in sections 
self.tableView.performUpdate({ 
      self.tableView.insertSections([newSectionIndex], with: UITableViewRowAnimation.top) 

     }, completion: { 
      // Scroll to next section 
      let nextSectionIndexPath = IndexPath(row: 0, section: newSectionIndex) 
      self.tableView.scrollToRow(at: nextSectionIndexPath, at: .top, animated: true) 
     }) 
+0

¡Respuesta impresionante! esta es una de las razones por las que amo Swift –

Cuestiones relacionadas