2009-08-27 14 views
10

Quiero hacer una serie de cosas en respuesta al final de ciertas animaciones de UITableView. Por ejemplo, quiero que la celda de vista de tabla resalte (mediante selectRowAtIndexPath) después de que se haya desplazado a scrollToRowAtIndexPath.¿Cómo saber cuándo se completa una animación UITableView?

¿Cómo se puede hacer esto?

Respuesta

-3

Bien si desea realizar una acción una vez que se ha disparado el scrollToRowAtIndexPath.

- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated 

lo necesario para crear un puntero CAAnimation como

CAAnimation *myAnimation; 

A continuación, establezca la delgate a la libre

myAnimation.delegate = self; 

Una vez hecho eso, estos siguientes métodos de delegado debe activar donde se puede poner su código:

- (void)animationDidStart:(CAAnimation *)theAnimation 

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag 
+5

como estas inicialización de su 'puntero myAnimation'? –

27

plantilla básica:

[UIView animateWithDuration:0.2 animations:^{ 
    //do some animations, call them with animated:NO 
} completion:^(BOOL finished){ 
    //Do something after animations finished  
}]; 

Ejemplo: Desplazamiento a la fila 100. Cuando haya terminado, obtener la célula en esta fila y hacer la vista de contenido de células con tag = 1 a la firstResponder:

[UIView animateWithDuration:0.2 animations:^{ 
     [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:100 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; 
    } completion:^(BOOL finished){ 
     //Do something after scrollToRowAtIndexPath finished, e.g.: 
     UITableViewCell *nextCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:100 inSection:0]]; 
     [[nextCell.contentView viewWithTag:1] becomeFirstResponder];   
    }]; 
+0

Esta es la respuesta más clara en SO para "Cómo realizar X después de que scrollToRowAtIndexPath se haya completado?" ¡Gracias! –

+1

No sé cómo funcionaba esta solución en iOS 4/5, pero ahora en iOS 6.1.4 y me doy cuenta de que justo después de que el contenidoOffset se modifique mediante scrollToRowAtIndexPath, las celdas en esta posición no son visibles, por lo que fracción de segundo, la vista de tabla está completamente en blanco, luego se dibujan las celdas y se muestra el teclado como se esperaba. Supongo que una UITableView no debe usarse de esta manera, o al menos no en esta versión de iOS. El mismo resultado ocurre usando setContentOffset en lugar de scrollToRowAtIndexPath. – ggould75

+0

No creo que esto esté funcionando – shim

2

I me di cuenta de esto en una publicación anterior pero estaba teniendo un problema similar y creé una solución que funcionó bien para mí. Apliqué las técnicas utilizadas en NSCookBook para crear UIAlertViews con bloques. El motivo por el que recurrí fue porque quería usar las animaciones incorporadas en lugar de UIView's + animateWithDuration: animations: completion :. Hay una gran diferencia entre estas animaciones con el cambio a iOS 7.

Crea una categoría para UITableView y en el archivo de implementación crea una clase interna privada que llamará al bloque asignándolo como delegado de la tabla. El problema es que hasta que se llame al bloque, el delegado original se "perderá", por así decirlo, ya que el nuevo delegado es el objeto que llamará al bloque. Es por eso que puse una notificación para enviar un mensaje cuando se ha llamado al bloque para reasignar el UITableViewDelegate original. Este código ha sido probado y está trabajando para mi fin.

// Header file 
@interface UITableView (ScrollDelegateBlock) 

-(void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath 
      atScrollPosition:(UITableViewScrollPosition)scrollPosition 
        animated:(BOOL)animated 
       scrollFinished:(void (^)())scrollFinished; 

@end 


// Implementation file 
#import "UITableView+ScrollDelegateBlock.h" 
#import <objc/runtime.h> 

NSString *const BLOCK_CALLED_NOTIFICATION = @"BlockCalled"; 

@interface ScrollDelegateWrapper : NSObject <UITableViewDelegate> 

@property (copy) void(^scrollFinishedBlock)(); 

@end 

@implementation ScrollDelegateWrapper 

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { 
    if (self.scrollFinishedBlock) { 
     [[NSNotificationCenter defaultCenter] postNotificationName:BLOCK_CALLED_NOTIFICATION object:nil]; 
     self.scrollFinishedBlock(); 
    } 
} 

@end 

static const char kScrollDelegateWrapper; 

static id<UITableViewDelegate>previousDelegate; 

@implementation UITableView (ScrollDelegateBlock) 

-(void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath 
      atScrollPosition:(UITableViewScrollPosition)scrollPosition 
        animated:(BOOL)animated 
       scrollFinished:(void (^)())scrollFinished { 
    previousDelegate = self.delegate; 
    ScrollDelegateWrapper *scrollDelegateWrapper = [[ScrollDelegateWrapper alloc] init]; 
    scrollDelegateWrapper.scrollFinishedBlock = scrollFinished; 
    self.delegate = scrollDelegateWrapper; 

    objc_setAssociatedObject(self, &kScrollDelegateWrapper, scrollDelegateWrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 

    [self scrollToRowAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(blockCalled:) 
               name:BLOCK_CALLED_NOTIFICATION 
               object:nil]; 
} 

/* 
* Assigns delegate back to the original delegate 
*/ 
-(void) blockCalled:(NSNotification *)notification { 
    self.delegate = previousDelegate; 
    [[NSNotificationCenter defaultCenter] removeObserver:self 
                name:BLOCK_CALLED_NOTIFICATION 
                object:nil]; 
} 

@end 

A continuación, puede llamar al método como cualquier otro con un bloque:

[self.tableView scrollToRowAtIndexPath:self.currentPath 
          atScrollPosition:UITableViewScrollPositionMiddle 
            animated:YES 
          scrollFinished:^{ 
           NSLog(@"scrollFinished"); 
          } 
]; 
+0

Gracias por publicar esto.Lo convertí a mi vista de colección y funciona perfecto. – Augie

+2

nota rápida: si la vista de desplazamiento ya está en la parte superior, el bloque de finalización no se activará. Necesito verificar la posición primero. – Augie

+0

Esto funciona, sin embargo, parece ignorar el heightForCell durante/después del desplazamiento. Tengo una celda más pequeña en la parte inferior de cada sección, sin embargo, este método hace que las celdas más pequeñas tengan el mismo tamaño que todas las demás. – Darren

Cuestiones relacionadas