pushViewController con escala de animation, que muestra background

He encontrado la manera de llamar a pushViewController con animation de escala, como el icono del menu principal de la aplicación Facebook, click animation. (new viewController es emergente desde el centro y se escala al tamaño original).

Busqué varios modos para cambiar la animation de pushViewController.

Primero, probé esto:

viewController.view.transform = CGAffineTransformMakeScale(0.5f, 0.5f); [UIView animateWithDuration:0.5f animations:^{ viewController.view.transform = CGAffineTransformMakeScale(1.0f, 1.0f); }]; [self.navigationController pushViewController:viewController animated:NO]; 

pero hay un problema, el viejo viewController desaparece cuando se inicia la animation, solo hay background blanco.

Si utilizo CATransition para cambiar la animation, puedo mostrar tanto el viewController antiguo como el nuevo, pero no hay animation de escala, solo se mueven, se presionan y se desvanecen en las animaciones.

Quiero mostrar el controller de vista nuevo y antiguo como las animaciones de CATransition, y necesito la forma de implementar mi animation personalizada.

Aquí está mi última sugerencia, manera sucia:

 [self.view addSubview:viewController.view]; viewController.view.transform = CGAffineTransformMakeScale(0.5f, 0.5f); [UIView animateWithDuration:0.5f delay:0.0f options:UIViewAnimationCurveEaseInOut animations:^{ viewController.view.alpha = 1.0f; viewController.view.transform = CGAffineTransformMakeScale(1.0f, 1.0f); } completion:^(BOOL finished) { [self.navigationController pushViewController:viewController animated:NO]; [viewController release]; }]; 

Primero, agregué new viewController.view como subvista, puedo mostrar la animation con una vista nueva y antigua. Cuando finalice la animation, pulse el controller de vista posterior.

De esta manera puedo implementar lo que pensé, pero creo que es sucio, y sigue habiendo un problema:

Los elementos de la barra de navigation no cambian inmediatamente, se cambia después de que finaliza la animation.

¿Hay alguna forma sencilla y clara de implementar esta animation? Creo que es imposible hacer eso sin cambiar la implementación original de pushViewController, ¿debería hacer subclassando pushViewController?

Gracias por leer y tu ayuda.

No creo que la animation se realice con un controller de vista. Puede simplemente mantener el controller de vista existente. Cree una nueva UIView que se supone debe ampliar. Agregue esa nueva UIView al controller de vista existente y aplique la animation a ella.

En respuesta a la pregunta original, no estoy seguro si consideras que es una mejora o no, pero creo que podrías include la barra de navigation en la vista que se está transformando (a) en IB, agregar una barra de navigation a tu (b) animar la ocultación de la barra de navigation del controller de navigation raíz antes de comenzar su animation (por lo que se desliza cuando su nueva vista se desliza), y (c) en el bloque de finalización de la animation, oculte la barra de navigation añadida de su nueva vista y mostrar la barra de navigation del controller de navigation raíz. Tal vez esto haga que algo esté más cerca de lo que pretendía, aunque probablemente sea diferente de lo que originalmente concibió. No es perfecto, sin embargo. El código podría parecerse a:

 MyViewController *newController = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil]; newController.view.transform = CGAffineTransformMakeScale(0.1f, 0.1f); [self.navigationController setNavigationBarHidden:YES animated:YES]; [self.view addSubview:newController.view]; [UIView animateWithDuration:0.5f delay:0.0f options:UIViewAnimationCurveEaseInOut animations:^{ newController.view.alpha = 1.0f; newController.view.transform = CGAffineTransformMakeScale(1.0f, 1.0f); } completion:^(BOOL finished) { [newController.view removeFromSuperview]; [self.navigationController pushViewController:newController animated:NO]; [newController.tempBar setHidden:YES]; [self.navigationController setNavigationBarHidden:NO animated:NO]; }]; 

Se está agregando un poco más de "suciedad" a su "manera sucia", pero podría representar el efecto que está buscando. Solo desea hacer que la barra de navigation temporal en su nueva vista se parezca lo mismo que la barra de navigation del controller de navigation raíz eventual, y el usuario no debería ser más sabio. Si esto aún no logra lo que estás buscando, solo puedes esconder la barra del controller de navigation raíz y siempre colocar tu navigation en tus vistas, en cuyo caso, el efecto será totalmente transparente a medida que pases a tu nueva vista.

Alternativamente, puede quedarse con su código existente y simplemente establecer el título de la vista actual antes de la transición, de esa manera podría parecer que el cambio de título sucedió por adelantado. Pero es probable que tengas que hacer algo para restablecerlo cuando vuelvas, configurando el button Atrás, etc., por lo que podría no valer la pena.

Como un aparte, y esto es un poco tangencial a la pregunta original (por lo que pido disculpas por adelantado), pero en respuesta a la otra sugerencia de que no debe animar el controller de vista, sino más bien solo las vistas, me gustaría express una palabra de precaución Sí, técnicamente así, pero estoy nervioso si esto alentará a las personas a adoptar la mala práctica de agregar nuevas vistas (a) creando un nuevo controller de vista; (b) animar la adición de la vista del controller de vista para que sea una subvista de la vista actual; pero (c) no hacer nada con ese nuevo controller de vista para agregarlo a la jerarquía del controller de vista (como pushViewController o presentViewController).

Si eso es lo que se pretendía para la otra respuesta, debo decir que creo que esta es una muy mala idea. (Si eso no es lo que se pretendía, mis disculpas, pero creo que es fácil para las personas interpretar mal la sugerencia). En pocas palabras, recientemente he visto a personas hacer cosas como:

 MyViewController *newController = [[MyViewController alloc] initWithNibName:@"MyView" bundle:nil]; // do some animation around adding the new view as a subview of your current view // but neglect to ever invoke pushViewController or presentViewController [self.view addSubview:newController.view]; 

Esto no se recomienda por un par de razones. Primero, si se trata de un proyecto ARC, su controller de vista se descartará cuando newController quede fuera de scope. (Parece que hay una avalancha de este tipo de preguntas que se publican en SO, como resultado de las excepciones que se lanzan a medida que la gente hace la transición a ARC). Seguro, puede solucionar esto haciendo que NewController sea un ivar de su controller principal para que no se caiga del scope, pero tenga cuidado de acordarse de configurarlo en cero cuando el controller principal se encuentre finalmente desasignado o al eliminar su subvista, o de lo contrario puede get una fuga. Y si se encuentra en un proyecto que no es ARC, es aún más fácil que se produzca una fuga, así que asegúrese de liberar el controller de vista cuando se quita la subvista para evitar fugas.

En segundo lugar, y probablemente más importante, mientras que el código anterior parece funcionar (o al less si convierte el controller en ivar), pero termina con una desconnection entre su jerarquía de los controlleres de vista y la de sus vistas. (En la session 102 de WWDC 2011 sobre un tema diferente, vea la contención del controller, incluye una discusión larga, pero relevante, sobre la importancia de mantener las jerarquías del controller de visualización y las jerarquías de visualización coordinadas, por ejemplo, los events de rotation pueden no enviarse correctamente a la nueva vista porque el controller no está en la jerarquía del controller, por lo que iOS no sabrá cómo enviarlos a su controller). En resumen, si usa la vista de otro controller de vista para agregar como una subvista de su vista actual, es frágil, es susceptible de romperse en las actualizaciones de iOS, y cosas como los events de rotation no se pasarán correctamente al controller de vista de su nueva vista. Si lo hace, al less sea consciente de que esto no es una buena práctica y realice su propia evaluación de riesgos en cuanto a si desea hacer eso. No es necesario eludir la jerarquía del controller de vista adecuada, y personalmente me gustaría disuadir a las personas que se inclinan a hacerlo.

En pocas palabras, si está haciendo una transición a una vista de un controller de vista diferente, realmente quiere adherirse a pushViewController o presentViewController, y hacer su animation alnetworkingedor de la vista del nuevo controller (y por lo general no es tan complicada como esta animation … en general es increíblemente simple y he hecho todo tipo de animaciones de desvanecimiento y flip con mucha mayor facilidad … es el uso de la transformada lo que hace que esto sea complicado).

Alternativa, si desea animar una nueva subvista UIView y no tratar con los controlleres de vista, solo asegúrese de que no sea la vista de otro controller de vista, sino, por ejemplo, una vista que cree mediante progtwigción que use el mismo controller de vista que su origen ver. Y si decide utilizar la vista de otro controller de vista como una subvista de su controller existente, simplemente hágalo sabiendo que es un poco frágil y que algunos events pueden no transmitirse a su nuevo controller de vista como espera y puede que no sea así "testing futura" como lo desee.