Tengo una aplicación basada en navegación y quiero cambiar la animación de las animaciones push y pop. ¿Como podría hacerlo?
Editar 2018
Ha habido muchas respuestas a esta pregunta y ha pasado bastante tiempo, he vuelto a elegir la respuesta a lo que creo que es el más relevante ahora. Si hay alguien que piense lo contrario, hágamelo saber en los comentarios
ios
animation
uinavigationcontroller
Pinchazo
fuente
fuente
Respuestas:
Para 2019, la "respuesta final".
Preámbulo:
Digamos que eres nuevo en el desarrollo de iOS. Confusamente, Apple proporciona dos transiciones que se pueden usar fácilmente. Estos son: "fundido cruzado" y "voltear".
Pero, por supuesto, "fundido cruzado" y "flip" son inútiles. Nunca se usan. ¡Nadie sabe por qué Apple proporcionó esas dos transiciones inútiles!
Entonces:
Digamos que desea hacer una transición común y corriente, como "diapositiva". En ese caso, ¡tienes que hacer una ENORME cantidad de trabajo! .
Ese trabajo, se explica en este post.
Solo para repetir:
Sorprendentemente: con iOS, si desea las transiciones cotidianas más simples, más comunes (como una diapositiva normal), debe realizar todo el trabajo de implementar una transición personalizada completa .
He aquí cómo hacerlo ...
1. Necesitas una costumbre
UIViewControllerAnimatedTransitioning
Necesitas un bool propio
popStyle
. (¿Está apareciendo o apareciendo?)Debe incluir
transitionDuration
(trivial) y la llamada principal,animateTransition
De hecho, debe escribir dos rutinas diferentes para el interior
animateTransition
. Uno para el empuje y otro para el pop. Probablemente los nombreanimatePush
yanimatePop
. En el interioranimateTransition
, simplemente bifurcapopStyle
a las dos rutinasEl siguiente ejemplo hace un simple movimiento de desplazamiento / desplazamiento
En tu
animatePush
yanimatePop
rutinas. Usted debe conseguir la "vista desde" y "a la vista". (Cómo hacerlo, se muestra en el ejemplo de código).y debe hacerlo
addSubview
para la nueva vista "a".y debes llamar
completeTransition
al final de tu animeEntonces ..
Y entonces ...
2. Úselo en su controlador de vista.
Nota: curiosamente, solo tiene que hacer esto en el "primer" controlador de vista. (El que está "debajo").
Con el que aparece en la parte superior , no haga nada . Fácil.
Entonces tu clase ...
se convierte en ...
Eso es.
Empuje y reviente exactamente como de costumbre, sin cambios. Para empujar ...
y para hacer estallar, puedes hacerlo si lo deseas en la siguiente pantalla:
Uf.
3. También disfrute las otras respuestas en esta página que explican cómo anular AnimatedTransition
¡Desplácese a @AlanZeino y @elias responden para más discusión sobre cómo usar las
AnimatedTransitioning
aplicaciones iOS en estos días!fuente
animatePush
yanimatePop
son ... ¡las dos direcciones diferentes!Hice lo siguiente y funciona bien ... y es simple y fácil de entender ...
Y lo mismo para empujar ..
Versión Swift 3.0:
fuente
Animated:NO
parte es vital. SiYES
se aprueba, las animaciones se mezclan y causan efectos divertidos.setViewControllers:
Así es como siempre he logrado completar esta tarea.
Para empujar:
Para el pop:
Todavía recibo muchos comentarios de esto, así que voy a seguir adelante y actualizarlo para usar bloques de animación, que es la forma recomendada por Apple de hacer animaciones de todos modos.
Para empujar:
Para el pop:
fuente
super
porself.navigationController
UIViewController
subclase un nombre sin la parte "ViewController"? Este nombre es más apropiado para UIView.para empujar
para pop
fuente
Respuesta de @Magnus, solo entonces para Swift (2.0)
Algunas notas al margen:
Puede hacer esto también con Segue, simplemente implemente esto en
prepareForSegue
oshouldPerformSegueWithIdentifier
. Sin embargo , esto también mantendrá la animación predeterminada. Para solucionar esto, debe ir al guión gráfico, hacer clic en Segue y desmarcar la casilla 'Animates'. Pero esto limitará su aplicación para IOS 9.0 y superior (al menos cuando lo hice en Xcode 7).Al hacerlo en una secuencia, las dos últimas líneas deben reemplazarse con:
Aunque establezco falso, lo ignora un poco.
fuente
¡Recuerda que en Swift , extension son definitivamente tus amigos!
fuente
Usar llamadas privadas es una mala idea, ya que Apple ya no aprueba las aplicaciones que lo hacen. Tal vez podrías intentar esto:
fuente
-pushViewController:transition:forceImmediate:
que sería una mala idea.Como este es el mejor resultado en Google, pensé en compartir lo que creo que es la forma más sensata; que es usar la API de transición de iOS 7+. Implementé esto para iOS 10 con Swift 3.
Es bastante simple combinar esto con la forma en que se
UINavigationController
anima entre dos controladores de vista si crea una subclase deUINavigationController
y devuelve una instancia de una clase que se ajusta alUIViewControllerAnimatedTransitioning
protocolo.Por ejemplo, aquí está mi
UINavigationController
subclase:Puede ver que configuré el
UINavigationControllerDelegate
mismo y, en una extensión de mi subclase, implemento el métodoUINavigationControllerDelegate
que le permite devolver un controlador de animación personalizado (es decir,NavigationControllerAnimation
). Este controlador de animación personalizado reemplazará la animación original por usted.Probablemente se esté preguntando por qué paso la operación a la
NavigationControllerAnimation
instancia a través de su inicializador. Hago esto para que enNavigationControllerAnimation
la implementación de laUIViewControllerAnimatedTransitioning
protocolo sepa cuál es la operación (es decir, 'push' o 'pop'). Esto ayuda a saber qué tipo de animación debo hacer. La mayoría de las veces, desea realizar una animación diferente según la operación.El resto es bastante estándar. Implemente las dos funciones requeridas en el
UIViewControllerAnimatedTransitioning
protocolo y anime como quiera:Es importante recordar que para cada tipo diferente de operación (es decir, 'push' o 'pop'), los controladores de vista de ida y vuelta serán diferentes. Cuando está en una operación de inserción, el controlador para ver será el que se está presionando. Cuando está en una operación emergente, el controlador de vista será el que se está haciendo la transición, y el controlador de vista será el que se está haciendo estallar.
Además, el
to
controlador de vista debe agregarse como una subvista delcontainerView
contexto de transición.Cuando finalice su animación, debe llamar
transitionContext.completeTransition(true)
. Si está haciendo una transición interactiva, tendrá que devolver dinámicamente unBool
acompleteTransition(didComplete: Bool)
, dependiendo de si la transición se completa al final de la animación.Finalmente ( lectura opcional ), es posible que desee ver cómo hice la transición en la que estaba trabajando. Este código es un poco más hacky y lo escribí bastante rápido, por lo que no diría que es un gran código de animación, pero aún muestra cómo hacer la parte de animación.
La mía fue una transición realmente simple; Quería imitar la misma animación que normalmente hace UINavigationController, pero en lugar de la animación 'siguiente página sobre la parte superior', quería implementar una animación 1: 1 del antiguo controlador de vista al mismo tiempo que la nueva vista aparece el controlador Esto tiene el efecto de hacer que los dos controladores de vista parezcan fijados entre sí.
Para la operación de inserción, eso requiere primero establecer el
toViewController
origen de la vista en el eje x fuera de la pantalla, agregarlo como la subvista delcontainerView
, animándolo en la pantalla al ponerloorigin.x
a cero. Al mismo tiempo, animé lafromViewController
vista de distancia al configurarlaorigin.x
fuera de la pantalla:La operación pop es básicamente la inversa. Agregue el
toViewController
como una subvista delcontainerView
, y animefromViewController
a la derecha como animatoViewController
desde la izquierda:Aquí hay un resumen de todo el archivo swift:
https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be
fuente
Hay UINavigationControllerDelegate y UIViewControllerAnimatedTransition allí, puedes cambiar la animación para lo que quieras.
Por ejemplo, esta es una animación pop vertical para VC:
}
Y entonces
Tutorial útil https://www.objc.io/issues/5-ios7/view-controller-transitions/
fuente
Basado en la respuesta actualizada para swift 4
jordanperry
Para empujar
UIViewController
Para el pop
fuente
Así es como he hecho lo mismo en Swift:
Para empujar:
Para el pop:
De hecho, hice esto un poco diferente a algunas de las respuestas anteriores, pero como soy nuevo en el desarrollo de Swift, puede que no sea correcto. He anulado
viewWillDisappear:animated:
y agregado el código pop allí:fuente
La respuesta de @Luca Davanzo en Swift 4.2
fuente
Hace poco estaba tratando de hacer algo similar. Decidí que no me gustaba la animación deslizante del UINavigationController, pero tampoco quería hacer las animaciones que UIView te da como curl o algo así. Quería hacer un fundido cruzado entre las vistas cuando presiono o hago estallar.
El problema allí implica el hecho de que la vista está literalmente eliminando la vista o colocando una sobre la parte superior de la actual, por lo que un fundido no funciona. La solución a la que llegué consistió en tomar mi nueva vista y agregarla como una subvista a la vista superior actual en la pila de UIViewController. Lo agrego con un alfa de 0, luego hago un fundido cruzado. Cuando finaliza la secuencia de animación, empujo la vista a la pila sin animarla. Luego vuelvo al viejo topView y limpio las cosas que había cambiado.
Es un poco más complicado que eso, porque tiene los elementos de navegación que tiene que ajustar para que la transición se vea correcta. Además, si realiza alguna rotación, debe ajustar el tamaño de los cuadros a medida que agrega las vistas como subvistas para que se muestren correctamente en la pantalla. Aquí hay algunos de los códigos que usé. Subclasifiqué el UINavigationController y anulé los métodos push y pop.
Como menciono en el código, siempre tengo un elemento de botón de barra izquierda, así que no verifico si es nulo antes de ponerlo en la matriz que paso como contexto para el delegado de animación. Si hace esto, es posible que desee hacer esa verificación.
El problema que encontré fue que si falla en el método delegado, no bloqueará el programa. Simplemente evita que el delegado se complete pero no recibe ningún tipo de advertencia.
Entonces, como estaba haciendo mi limpieza en esa rutina de delegado, estaba causando un comportamiento visual extraño ya que no estaba terminando la limpieza.
El botón Atrás que creo llama a un método "goBack", y ese método solo llama a la rutina pop.
Además, aquí está mi rutina pop.
Eso es practicamente todo. Necesitará un código adicional si desea implementar rotaciones. Tendrá que establecer el tamaño de marco de sus vistas que agregue como subvistas antes de mostrarlas; de lo contrario, se encontrará con problemas, la orientación es horizontal, pero la última vez que vio la vista anterior fue vertical. Entonces, lo agrega como una vista secundaria y se desvanece, pero aparece como retrato, luego, cuando aparecemos sin animación, la misma vista, pero la que está en la pila, ahora es horizontal. Todo parece un poco raro. La implementación de rotación de todos es un poco diferente, así que no incluí mi código para eso aquí.
Espero que ayude a algunas personas. He buscado algo como esto y no he podido encontrar nada. No creo que esta sea la respuesta perfecta, pero en este momento me está funcionando muy bien.
fuente
Ahora puedes usar
UIView.transition
. Tenga en cuenta queanimated:false
. Esto funciona con cualquier opción de transición, pop, push o reemplazo de pila.fuente
Usando la respuesta de iJordan como inspiración, ¿por qué no simplemente crear una Categoría en UINavigationController para usar en toda su aplicación en lugar de copiar / pegar este código de animación en todo el lugar?
UINavigationController + Animation.h
UINavigationController + Animation.m
Luego, simplemente importe el archivo UINavigationController + Animation.h y llámelo normalmente:
fuente
Es muy simple
fuente
Eche un vistazo a ADTransitionController , un reemplazo sustitutivo de UINavigationController con animaciones de transición personalizadas (su API coincide con la API de UINavigationController) que creamos en Applidium.
Puede usar diferentes animaciones predefinidas para acciones push y pop como Swipe , Fade , Cube , Carrousel , Zoom , etc.
fuente
Si bien todas las respuestas aquí son excelentes y la mayoría funciona muy bien, hay un método un poco más simple que logra el mismo efecto ...
Para empujar:
Para el pop:
fuente
No conozco ninguna forma de cambiar públicamente la animación de transición.
Si el botón "atrás" no es necesario, debe usar controladores de vista modal para que las transiciones "empujar desde abajo" / "voltear" / "desvanecerse" / (≥3.2) "curvar página".
En el lado privado , el método
-pushViewController:animated:
llama al método no documentado-pushViewController:transition:forceImmediate:
, por lo que, por ejemplo, si desea una transición de giro de izquierda a derecha, puede usarSin embargo, no puede cambiar la transición "pop" de esta manera.
fuente
Vea mi respuesta a esta pregunta para saber cómo hacerlo en muchas menos líneas de código. Este método le permite animar un pseudo- "Empuje" de un nuevo controlador de vista de la manera que desee, y cuando se realiza la animación, configura el Controlador de navegación como si hubiera utilizado el método Push estándar. Mi ejemplo le permite animar un deslizamiento desde la izquierda o desde la derecha. Código repetido aquí por conveniencia:
fuente
Desde la aplicación de muestra, mira esta variación. https://github.com/mpospese/MPFoldTransition/
fuente
Solo usa:
fuente
Darse cuenta de esto es una vieja pregunta. Todavía me gustaría publicar esta respuesta, ya que tuve algunos problemas para mostrar varias
viewControllers
de las respuestas propuestas. Mi solución es subclasificarUINavigationController
y anular todos los métodos pop y push.FlippingNavigationController.h
FlippingNavigationController.m:
fuente
Sé que este hilo es viejo, pero pensé en poner mis dos centavos. No necesita hacer una animación personalizada, hay una manera simple (quizás hacky) de hacerlo. En lugar de usar push, cree un nuevo controlador de navegación, haga que el nuevo controlador de vista sea el controlador de vista raíz de ese controlador de navegación, y luego presente el controlador de navegación desde el controlador de navegación original. El presente es fácilmente personalizable con muchos estilos, y no es necesario hacer una animación personalizada.
Por ejemplo:
Y puedes cambiar el estilo de presentación como quieras.
fuente
Encontré una forma ligeramente recursiva de hacer esto que funciona para mis propósitos. Tengo una variable de instancia BOOL que uso para bloquear la animación emergente normal y sustituir mi propio mensaje pop no animado. La variable se establece inicialmente en NO. Cuando se toca el botón Atrás, el método delegado lo establece en SÍ y envía un nuevo mensaje emergente no animado a la barra de navegación, llamando así al mismo método delegado nuevamente, esta vez con la variable establecida en SÍ. Con la variable establecida en SÍ, el método delegado la establece en NO y devuelve SÍ para permitir que ocurra el pop no animado. Después de que regresa la segunda llamada de delegado, terminamos nuevamente en la primera, donde NO se devuelve, ¡bloqueando el pop animado original! En realidad no es tan desordenado como parece. Mi método shouldPopItem se ve así:
Funciona para mi.
fuente