2011-10-07 20 views
9

En mi aplicación para iPad tengo un controlador de vista con una pequeña vista de tabla. Cuando toca en la vista de tabla, abre un controlador de vista modal que es una versión más grande y más refinada de la vista de tabla pequeña. Me gustaría crear una animación a partir de una imagen renderizada previamente del controlador de vista grande escalando la imagen para que sea del tamaño de la vista de tabla pequeña y acercarla al tamaño de pantalla completa y luego reemplazar la imagen con la vista "real" controlador.¿Cómo presento un UIViewController haciendo zoom?

Algo así como:

LargeViewController* lvc = [[LargeViewController alloc] init]; 
[self presentModalViewController:lvc byZoomingFromRect:CGRectMake(50,50,200,300)]; 

Sé que puede producir una imagen desde un punto de vista:

- (UIImage *) imageWithView:(UIView *)view 
{ 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]); 
    [view.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return img; 
} 

Pero cómo hago la misma (fuera de pantalla) sorteo controlador de vista para que pueda tomar su ver y escalar la imagen en una animación para llenar la pantalla?

Gracias de antemano.

Respuesta

3

Supongo que quiere crear su propia animación. El mes pasado jugué con algo así. Mi solución fue agregar una vista personalizada (tal vez tomada desde un controlador de vista) a la vista actual como una superposición. Esto funciona con capas, también.

Primero busca la imagen de su controlador de vista "futuro" o "presente", como lo hizo en el ejemplo de código anterior. Normalmente, el contenido de los controladores de vista debe estar disponible mientras se procesa en el contexto.

Ahora usted tiene la imagen. La manipulación de la imagen debe ser hecha por usted.

Agregue la imagen a un UIImageView. Este ImageView se puede agregar como subvista o capa. Ahora tiene una capa donde puede dibujar libremente sobre su interfaz de usuario real. A veces tiene que mover la capa o ver alrededor, de modo que superpone perfectamente su vista. Esto depende de la configuración de tu vista. Si está trabajando con Tableviews, agregar una subvista no es tan fácil. Así que mejor usa la capa.

Después de todo el trabajo realizado, presente el nuevo controlador de vista sin animación, para que aparezca inmediatamente.

Elimine la capa o vista de su vista principal después de que el trabajo haya terminado, y limpie.

Esto suena complicado, pero una vez que lo haya hecho, tiene una plantilla para eso. En "WWDC 2011, Session 309 Introducing Interface Builder Storyboarding", Apple introdujo 'segues personalizados', donde encontrará un mecanismo para exactamente lo que quiere hacer. El siguiente código es un recorte de un proyecto anterior y de alguna manera es complicado y debe ser limpiado. Pero para mostrar el principio esto debería funcionar:

-(void) animate { 

     static LargeViewController* lvc = [[LargeViewController alloc] init]; 

     UIGraphicsBeginImageContextWithOptions(self.bounds.size, view.opaque, [[UIScreen mainScreen] scale]); 
    [lvc.view.layer renderInContext:UIGraphicsGetCurrentContext()]; 

     // Create a ImageView to display your "zoomed" image 
     static UIImageView* displayView = [[UIImageView alloc] initWithFrame:self.view.frame]; 
     static UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 

     // Add your image to the view 
     displayView.image = img; 

     // insert the view above your actual view, adjust coordinates in the 
     // frame property of displayView if overlay is misaligned 
     [[self.view] addSubview:displayView]; 

     // alternatively you can use the layer 
     // [self.view.layer addSublayer:displayView.layer]; 

     // draw the imageView 
     [displayView setNeedsDisplay]; 

     // do something in background. You may create your own 
     // construction, i.e. using a timer 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

      NSDate *now = [NSDate date]; 
      NSTimeInterval animationDuration = 3.; 
      NSTimeInterval t = -[now timeIntervalSinceNow]; 
      while (t < animationDuration) { 

       t = -[now timeIntervalSinceNow]; 

       // Do some animation here, by manipulation the image 
       // or the displayView 

       // <calculate animation>, do something with img 
       // you have exact timing information in t, 
       // so you can set the scalefactor derived from t 
       // You must not use an UIImage view. You can create your own view 
       // and do sth. in draw rect. Do whatever you want, 
       // the results will appear 
       // in the view if you added a subview 
       // or in a layer if you are using the layer 

       dispatch_sync(dispatch_get_main_queue(), ^{ 

        // display the result 
        displayView.image = img; 
        [displayView setNeedsDisplay]; 
       }); 
      } 
     }); 

     // now the animation is done, present the real view controller 
     [self presentModalViewController:lvc animated:NO]; 

     // and clean up here 
} 
+0

Finalmente tuve tiempo de probar sus sugerencias, muy detalladas. ¡Funciona de maravilla! ¡Muchas gracias por tu aportación! Y también, la sesión 309 de la WWDC 2011 con conexiones personalizadas también habría funcionado muy bien. –

0

Tal vez usted podría utilizar algo como

CGAffineTransform tr = CGAffineTransformScale(lvc.view.transform, 0.5, 0.5); 

incrustar una versión reducida de la vista en su controlador de vista de los padres, a continuación, presente de forma modal LVC y restaurar la escala cuando el usuario toca la vista.

0

UIKit se encarga de la mayor parte de esto por usted. Si bien la solución de jbat100 también podría funcionar, debería poder hacer esto simplemente configurando el marco inicial de lvc en el rectángulo más pequeño al que desea comenzar, y luego, cuando ajuste el marco a su tamaño completo, la animación implícita para cambiar el marco manejará la animación de acercamiento por usted. Cada UIView tiene un CALayer de que su contenido está dibujado y esa capa tiene varias animaciones implícitas configuradas para cambios animados a ciertas propiedades, como las propiedades de marco o posición. Aquí está mi arma blanca no probado en ella:

 . 
     . 
    lvc.view.frame = CGRectMake(50,50,200,300); 
    [self performSelector:@selector(setFrameToFullScreen) withObject:nil afterDelay:0]; 

} 

- (void)setFrameToFullScreen { 
    lcv.view.frame = [UIScreen mainScreen].bounds; 
} 

La llamada performSelector:withObject:afterDelay causará setFrameToFullScreen para ser llamado en el siguiente ciclo de bucle de ejecución. Si no hace algo así, solo se usará el fotograma final y el sistema no reconocerá el cambio en el fotograma y aplicará su animación implícita a la capa de vistas.

+0

El problema es que un controlador de vista no tiene una propiedad de marco ya que no es una clase de vista. La única manera que conozco de mostrar un controlador de vista es mediante el uso del método presentModalViewController: animado: y ese método establece la animación en sí misma. –

+0

¡Su derecho! el controlador de vista no tiene un marco, pero su vista sí lo tiene. Edité el código de arriba para reflejar eso. – Logachu

Cuestiones relacionadas