Tengo una navegación basada en la aplicación y quiero cambiar la animación de la push y pop animaciones. ¿Cómo puedo hacer eso?

Edición de 2018

Ha habido muchas respuestas a esta pregunta y ha sido bastante tiempo ahora, he re-elegido la respuesta a lo que yo creo, es la más relevante ahora. Si hay alguien que piensa lo contrario, por favor, hágamelo saber en los comentarios

  • Como de iOS 7, no es oficial de la API para esto; ver UINavigationControllerDelegate‘s personalizados de animación de transición de apoyo. También hay un la WWDC 2013 Video acerca de este.
  • He añadido una respuesta (a continuación) para hacer esto en Swift – me encontré con esta pregunta acerca de Swift implementaciones así que pensé en hablar con mi posterior implementación.
  • Para un tutorial muy bueno con el oficial (iOS 7+) de la API, consulte: bradbambara.wordpress.com/2014/04/11/…
  • link actualizado para la WWDC 2013 Video: developer.apple.com/videos/play/wwdc2013-218
  • Para el 2018 ! Para este muy antiguo control de calidad, hoy en día el uso de UIViewControllerAnimatedTransitioning. Me puse en una respuesta hacia abajo la parte inferior. Feliz año nuevo!
  • Cambió mi aceptado la respuesta de los chicos n chicas. Espero que esto ayude! GLHF

InformationsquelleAutor Jab | 2010-02-07

25 Comentarios

  1. 25

    Cómo cambiar el Push y Pop animaciones en una navegación de la aplicación…

    Para el año 2019, la «respuesta final!»

    Preámbulo:

    Decir que son nuevos en el desarrollo de iOS. Confusamente, Apple proporcionar dos transiciones que puede ser utilizado fácilmente. Estos son: «fundido» y «flip».

    Pero, por supuesto, «fundido» y «flip» son inútiles. No se utilizan nunca. Nadie sabe por qué Apple siempre esos dos inútiles transiciones!

    Así:

    Decir que quieres hacer ordinario, común, de transición como «slide». En ese caso, que usted tiene que hacer una ENORME cantidad de trabajo!.

    Que trabajo, está explicado en este post.

    Sólo para repetir:

    Sorprendentemente: con iOS, si desea que el más simple, más común, cotidiano transiciones (como ordinaria de la diapositiva), usted tiene que todo el trabajo de la implementación de un totalmente a la medida de transición.

    Aquí está cómo hacerlo …

    1. Usted necesita una costumbre UIViewControllerAnimatedTransitioning

    1. Usted necesita un bool de su propio como popStyle . (Es de hacer estallar en, o estallar fuera?)

    2. Debe incluir transitionDuration (trivial) y el llamado principal, animateTransition

    3. De hecho, usted debe escribir dos diferentes rutinas para dentro de animateTransition. Uno para el empuje, y uno para el pop. Probablemente el nombre de ellos animatePush y animatePop. Dentro de animateTransition, acaba de rama en popStyle a las dos rutinas

    4. El ejemplo siguiente hace un movimiento simple-más de/move-off

    5. En su animatePush y animatePop rutinas. Usted debe obtener el «de la vista» y el «a ver». (Cómo hacerlo, se muestra en el ejemplo de código.)

    6. y debe addSubview para la nueva «a» de la vista.

    7. y debe llamada completeTransition al final de su anime

    Así ..

      class SimpleOver: NSObject, UIViewControllerAnimatedTransitioning {
    var popStyle: Bool = false
    func transitionDuration(
    using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return 0.20
    }
    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    if popStyle {
    animatePop(using: transitionContext)
    return
    }
    let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
    let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
    let f = transitionContext.finalFrame(for: tz)
    let fOff = f.offsetBy(dx: f.width, dy: 55)
    tz.view.frame = fOff
    transitionContext.containerView.insertSubview(tz.view, aboveSubview: fz.view)
    UIView.animate(
    withDuration: transitionDuration(using: transitionContext),
    animations: {
    tz.view.frame = f
    }, completion: {_ in 
    transitionContext.completeTransition(true)
    })
    }
    func animatePop(using transitionContext: UIViewControllerContextTransitioning) {
    let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
    let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
    let f = transitionContext.initialFrame(for: fz)
    let fOffPop = f.offsetBy(dx: f.width, dy: 55)
    transitionContext.containerView.insertSubview(tz.view, belowSubview: fz.view)
    UIView.animate(
    withDuration: transitionDuration(using: transitionContext),
    animations: {
    fz.view.frame = fOffPop
    }, completion: {_ in 
    transitionContext.completeTransition(true)
    })
    }
    }

    Y, a continuación, …

    2. Utilizar en su controlador de vista.

    Nota: extraño, sólo tienes que hacer esto en la «primera» vista controlador. (El que está «debajo de».)

    Con el que el pop en superior, hacer nada. Fácil.

    Por lo que su clase…

    class SomeScreen: UIViewController {
    }

    se convierte en…

    class FrontScreen: UIViewController,
    UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {
    let simpleOver = SimpleOver()
    override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.delegate = self
    }
    func navigationController(
    _ navigationController: UINavigationController,
    animationControllerFor operation: UINavigationControllerOperation,
    from fromVC: UIViewController,
    to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    simpleOver.popStyle = (operation == .pop)
    return simpleOver
    }
    }

    Que es.

    De Push y pop exactamente como normal, no hay cambio. A empujar …

    let n = UIStoryboard(name: "nextScreenStoryboardName", bundle: nil)
    .instantiateViewController(withIdentifier: "nextScreenStoryboardID")
    as! NextScreen
    navigationController?.pushViewController(n, animated: true)

    y pop, puedes, si te gusta solo hacer que en la pantalla siguiente:

    class NextScreen: TotallyOrdinaryUIViewController {
    @IBAction func userClickedBackOrDismissOrSomethingLikeThat() {
    navigationController?.popViewController(animated: true)
    }
    }

    Ufff.


    3. También disfrutar de las otras respuestas en esta página en la que explican cómo reemplazar AnimatedTransitioning

    Desplazarse a @AlanZeino y @elias respuesta para más discusión sobre cómo AnimatedTransitioning en las apps de iOS en estos días!

    • Excelente! Si quiero que la navegación pase de nuevo gesto de apoyo a la misma AnimatedTransitioning demasiado. Alguna idea?
    • gracias @samchiwen – de hecho, eso es exactamente lo que animatePush y animatePop son .. las dos direcciones diferentes!
  2. 264

    Hice lo siguiente y funciona bien.. y es simple y fácil de entender..

    CATransition* transition = [CATransition animation];
    transition.duration = 0.5;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
    //transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
    [self.navigationController.view.layer addAnimation:transition forKey:nil];
    [[self navigationController] popViewControllerAnimated:NO];

    Y la misma cosa para empujar..


    Swift versión 3.0:

    let transition = CATransition()
    transition.duration = 0.5
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.type = kCATransitionFade
    self.navigationController?.view.layer.add(transition, forKey: nil)
    _ = self.navigationController?.popToRootViewController(animated: false)
    • +1, esto realmente es el más cuerdo de la solución. Sólo una nota menor de edad para los futuros visitantes: el Animated:NO parte es de vital importancia. Si YES se pasa, las animaciones mezcla y causan efectos divertidos.
    • La mejor solución hasta ahora.. Y para los principiantes, no te olvides de incluir QuartCore (#import <QuartzCore/QuartzCore.h>)
    • Parece que este enfoque tiene un mejor rendimiento, sin embargo, cómo hacer que la pantalla gire de izquierda a derecha, como el UIView animación solución con la UIViewAnimationTransitionFlipFromleft opción. He probado con todas las de la transición tipos, pero no lo veo tal efecto.
    • Hay un ejemplo en el que este código funciona? No sé por qué no puedo hacer que se vaya.
    • El único problema que tengo con esta solución que la empuja viewcontroller del viewDidAppear se llama inmediatamente después de la empujo sin animación. Es allí una manera alrededor de ella?
    • Mi problema con este código es cada vista parece flash, gris o blanco, mientras se deslizan dentro o fuera.
    • comprueba en iOS 7.1.2 y iOS 8.3 — este código está funcionando bien también trabaja muy bien para el método setViewControllers:
    • Para swift: stackoverflow.com/a/31405594/2901207
    • Perfecto, pero una cosa más que para ocultar la barra de navegación, el uso de este [auto.navigationController setNavigationBarHidden:SI animado:NO];
    • no su trabajo cuando VC es empujado ..funciona cuando apareció
    • Para hacer Uso de: de la transición.tipo = kCATransitionPush; transición.subtipo = kCATransitionFromLeft;//Correcto
    • No funciona en el caso de opengl basado en uso de las vistas en el controlador de destino. Alan Zeino método de trabajo.
    • Este 7 de yr respuesta es, honestamente, no es una solución. Es uno de esos casos en LO que una «solución rápida», que realmente no se mucho de upvotes! Realmente con los grandes cambios de iOS desde entonces, simplemente no es viable, por desgracia.
    • De nuevo, puramente para cualquier persona googlear aquí, este 8 años de edad de respuesta no funciona en la actualidad. Yo actualización de la respuesta de abajo (ver «2018») cada mes o dos meses por lo que tiene la última Swift sintaxis. Ahora hay un par de respuestas que el uso correcto del enfoque moderno. Es un buen ejemplo de cómo en TAN, algunas de las respuestas a llegar muy, muy fuera de fecha.
    • Para mi caso simple donde yo quiera despedir a un VC al con un desvanecimiento de la animación, esta solución funciona bien. ¿Qué quieres decir con ‘no funciona’?

  3. 256

    Esto es lo que he hecho siempre se las arregló para completar esta tarea.

    Para Empujar:

    MainView *nextView=[[MainView alloc] init];
    [UIView  beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:0.75];
    [self.navigationController pushViewController:nextView animated:NO];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
    [UIView commitAnimations];
    [nextView release];

    Pop:

    [UIView  beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:0.75];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
    [UIView commitAnimations];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDelay:0.375];
    [self.navigationController popViewControllerAnimated:NO];
    [UIView commitAnimations];


    Todavía tengo un montón de comentarios de este, así que voy a seguir adelante y actualizar el uso de la animación de bloques, que es el de Apple método recomendado para hacer animaciones de todos modos.

    Para Empujar:

    MainView *nextView = [[MainView alloc] init];
    [UIView animateWithDuration:0.75
    animations:^{
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [self.navigationController pushViewController:nextView animated:NO];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
    }];

    Pop:

    [UIView animateWithDuration:0.75
    animations:^{
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
    }];
    [self.navigationController popViewControllerAnimated:NO];
    • Gracias por este. Pero el pop es hecho automáticamente por el UINavigationController. ¿Cómo se puede reemplazar este comportamiento para que usted puede llamar a su costumbre pop lógica?
    • realmente funciona!!! sólo tienes que sustituir super por self.navigationController
    • Es allí cualquier manera de conseguir una diapositiva de la izquierda en lugar de la diapositiva predeterminada de la derecha?
    • La primera no mostrar el nuevo punto de vista en absoluto. El segundo no mostrar animación. Muy mala respuesta! iOS 7.
    • Esto todavía funciona bien para mí en iOS 7.
    • Si tenemos en cuenta lo que esto está haciendo, esto es realmente una solución simple. Esencialmente, usted está diciendo a la navegación controlador no para hacer su propia animación en su vista y teniendo cuidado de ti mismo.
    • Ver esta respuesta para un ejemplo de cómo rodar este código en una Categoría en la UINavigationController para facilitar la reutilización: stackoverflow.com/a/19910967/1103584
    • ¿por qué has dado a UIViewController subclase de un nombre sin «ViewController» parte. Este nombre es más apropiado para UIView.
    • Swift 3 solución, por favor?

  4. 29

    para empujar

    CATransition *transition = [CATransition animation];
    transition.duration = 0.3;
    transition.type = kCATransitionFade;
    //transition.subtype = kCATransitionFromTop;
    [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
    [self.navigationController pushViewController:ViewControllerYouWantToPush animated:NO];

    pop

    CATransition *transition = [CATransition animation];
    transition.duration = 0.3;
    transition.type = kCATransitionFade;
    //transition.subtype = kCATransitionFromTop;
    [self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
    [self.navigationController popViewControllerAnimated:NO];
  5. 19

    @Magnus respuesta, sólo entonces para Swift (2.0)

        let transition = CATransition()
    transition.duration = 0.5
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromTop
    self.navigationController!.view.layer.addAnimation(transition, forKey: nil)
    let writeView : WriteViewController = self.storyboard?.instantiateViewControllerWithIdentifier("WriteView") as! WriteViewController
    self.navigationController?.pushViewController(writeView, animated: false)

    Algunos sidenotes:

    Usted puede hacer esto también con Segue, acaba de implementar esto en prepareForSegue o shouldPerformSegueWithIdentifier. Sin embargo, esto evitará que la animación por defecto en ella. Para solucionar esto tienes que ir al guión gráfico, haga clic en el Pase y desmarque la casilla de ‘Anima’. Pero esto limitará su aplicación para IOS 9.0 y superior (al menos cuando yo lo hice en Xcode 7).

    Cuando se hace en una continuación, las dos últimas líneas se debe reemplazar con:

    self.navigationController?.popViewControllerAnimated(false)

    A pesar de que yo se establece en false, el tipo le ignora.

    • Cómo quitar el color negro en el fondo al final de la animación.
    • No trabajar por el empuje de controlador de vista de trabajos de animación para Pop vista controlador
  6. 16

    Recordar que en Swift, extensión son sin duda tus amigos!

    public extension UINavigationController {
    /**
    Pop current view controller to previous view controller.
    - parameter type:     transition animation type.
    - parameter duration: transition animation duration.
    */
    func pop(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
    self.addTransition(transitionType: type, duration: duration)
    self.popViewControllerAnimated(false)
    }
    /**
    Push a new view controller on the view controllers's stack.
    - parameter vc:       view controller to push.
    - parameter type:     transition animation type.
    - parameter duration: transition animation duration.
    */
    func push(viewController vc: UIViewController, transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
    self.addTransition(transitionType: type, duration: duration)
    self.pushViewController(vc, animated: false)
    }
    private func addTransition(transitionType type: String = kCATransitionFade, duration: CFTimeInterval = 0.3) {
    let transition = CATransition()
    transition.duration = duration
    transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.type = type
    self.view.layer.addAnimation(transition, forKey: nil)
    }
    }
  7. 10

    Mediante llamadas privadas es una mala idea, ya que Apple ya no aprobar las aplicaciones que hacen eso.
    Tal vez usted podría tratar este:

    //Init Animation
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration: 0.50];
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];
    //Create ViewController
    MyViewController *myVC = [[MyViewController alloc] initWith...];
    [self.navigationController pushViewController:myVC animated:NO];
    [myVC release];
    //Start Animation
    [UIView commitAnimations];
    • Sólo «la mitad» de las obras – no va a resolver el difícil problema de pop animaciones.
    • Me gusta esta solución mejor, y sí funciona. El uso de métodos privados conseguirá que rechazó seguro.
    • que es la llamada a la api. No me di cuenta.
    • hubo una discusión aquí hace un tiempo en torno al uso del -pushViewController:transition:forceImmediate: que sería una mala idea.
  8. 9

    Ya que este es el primer resultado en Google he pensado que me gustaría compartir lo que creo que es lo más cuerdo modo, lo que es usar el iOS 7+ la transición de la API. He implementado esta para iOS 10 con Swift 3.

    Es muy simple de combinar esto con cómo UINavigationController anima entre dos controladores si se crea una subclase de UINavigationController y devolver una instancia de una clase que se ajusta a la UIViewControllerAnimatedTransitioning protocolo.

    Por ejemplo, aquí está mi UINavigationController subclase:

    class NavigationController: UINavigationController {
    init() {
    super.init(nibName: nil, bundle: nil)
    delegate = self
    }
    required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
    }
    }
    extension NavigationController: UINavigationControllerDelegate {
    public func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    return NavigationControllerAnimation(operation: operation)
    }
    }

    Se puede ver que puedo establecer la UINavigationControllerDelegate a sí mismo, y en una extensión de mi subclase puedo implementar el método en UINavigationControllerDelegate que le permite devolver una animación personalizada controlador (es decir, NavigationControllerAnimation). Esta animación personalizada controlador de reemplazar las acciones de animación para usted.

    Te estás preguntando por qué te paso en la operación de la NavigationControllerAnimation ejemplo, a través de su inicializador. Hago esto para que en NavigationControllerAnimation‘s de aplicación de la UIViewControllerAnimatedTransitioning protocolo sé lo que la operación es (es decir, ‘empuje’ o ‘pop’). Esto ayuda a saber qué tipo de animación que debo hacer. La mayoría de las veces, usted desea realizar una animación diferente dependiendo de la operación.

    El resto es bastante estándar. Implementar las dos funciones requeridas en el UIViewControllerAnimatedTransitioning protocolo y animar sin embargo te gusta:

    class NavigationControllerAnimation: NSObject, UIViewControllerAnimatedTransitioning {
    let operation: UINavigationControllerOperation
    init(operation: UINavigationControllerOperation) {
    self.operation = operation
    super.init()
    }
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return 0.3
    }
    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    guard let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
    let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { return }
    let containerView = transitionContext.containerView
    if operation == .push {
    //do your animation for push
    } else if operation == .pop {
    //do your animation for pop
    }
    }
    }

    Es importante recordar, que para cada tipo de operación (es decir, ‘empuje’ o ‘pop), la a y de la vista de los controladores serán diferentes. Cuando usted está en una operación de inserción, a la vista controlador será el de ser empujado. Cuando usted está en un pop operación, el controlador de vista será el que se está transfiriendo, y el de la vista controlador va a ser el uno que se hizo estallar.

    También, la to vista controlador debe ser añadido como una subvista de la containerView en el contexto de transición.

    Cuando la animación completa, debe llamar a transitionContext.completeTransition(true). Si usted está haciendo un interactiva de transición, usted tendrá dinámicamente devolver un Bool a completeTransition(didComplete: Bool), dependiendo de si la transición se completa al final de la animación.

    Finalmente (de lectura opcional), es posible que desee ver cómo me hizo la transición en el que estaba trabajando. Este código es un poco más chapucero y lo escribí muy rápido así que no diría que la gran animación de código pero todavía muestra cómo hacer la animación.

    Mina era realmente una simple transición; quería imitar la misma animación que UINavigationController normalmente se hace, pero en lugar de la ‘página siguiente sobre la parte superior de animación se hace, yo quería implementar un 1:1 de la animación de la vista anterior del controlador de distancia en el mismo tiempo que el nuevo controlador de vista aparece. Esto tiene el efecto de hacer que las dos controladores parecen como si estuvieran pegados a cada uno de los otros.

    Para la operación de inserción, que requiere en primer lugar la configuración de la toViewController‘s de la vista de origen sobre el eje x fuera de la pantalla, añadiendo como la subvista de la containerView, la animación en pantalla de ajuste que origin.x a cero. Al mismo tiempo, me anime la fromViewController‘s vista a través de su origin.x fuera de la pantalla:

    toViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.size.width, dy: 0.0)
    containerView.addSubview(toViewController.view)
    UIView.animate(withDuration: transitionDuration(using: transitionContext),
    delay: 0,
    options: [ UIViewAnimationOptions.curveEaseOut ],
    animations: {
    toViewController.view.frame = containerView.bounds
    fromViewController.view.frame = containerView.bounds.offsetBy(dx: -containerView.frame.size.width, dy: 0)
    },
    completion: { (finished) in
    transitionContext.completeTransition(true)
    })

    El funcionamiento del pop es básicamente la inversa. Agregar el toViewController como una subvista de la containerView, y la animación de lejos el fromViewController a la derecha, como la animación en el toViewController de la izquierda:

    containerView.addSubview(toViewController.view)
    UIView.animate(withDuration: transitionDuration(using: transitionContext),
    delay: 0,
    options: [ UIViewAnimationOptions.curveEaseOut ],
    animations: {
    fromViewController.view.frame = containerView.bounds.offsetBy(dx: containerView.frame.width, dy: 0)
    toViewController.view.frame = containerView.bounds
    },
    completion: { (finished) in
    transitionContext.completeTransition(true)
    })

    Aquí un gist con todo el swift de archivo:

    https://gist.github.com/alanzeino/603293f9da5cd0b7f6b60dc20bc766be

    • Genial!!!. Lo que yo quería hacer es animar en dirección opuesta. Examiné algunas otras soluciones, pero todas exposición intermitente a la izquierda y a la derecha de la pantalla. Parece implícito alfa cambiar la animación no puede ser eliminado con ellos. La única solución rectificar el problema.
    • sí, esta es la única correcta solución moderna. (No me importa, pero es exactamente el mismo que el de la solución que he escrito a continuación! 🙂 )
    • Lo que si dentro de la misma ViewController usted necesita tener diferente Animaciones para diferentes haga clic con el botón? Así, por button1 necesita una disolver la animación, para button2 necesita la transición predeterminada.
  9. 7

    Hay UINavigationControllerDelegate y UIViewControllerAnimatedTransitioning no se puede cambiar la animación de todo lo que quieras.

    Por ejemplo, esta es vertical pop animación para VC:

    @objc class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
    return 0.5
    }
    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
    let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
    let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
    let containerView = transitionContext.containerView()
    let bounds = UIScreen.mainScreen().bounds
    containerView!.insertSubview(toViewController.view, belowSubview: fromViewController.view)
    toViewController.view.alpha = 0.5
    let finalFrameForVC = fromViewController.view.frame
    UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
    fromViewController.view.frame = CGRectOffset(finalFrameForVC, 0, bounds.height)
    toViewController.view.alpha = 1.0
    }, completion: {
    finished in
    transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
    })
    }

    }

    Y, a continuación,

    func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    if operation == .Pop {
    return PopAnimator()
    }
    return nil;
    }

    Útil tutorial
    https://www.objc.io/issues/5-ios7/view-controller-transitions/

  10. 6

    Basado en jordanperry respuesta actualizado para swift 4

    Para empujar UIViewController

    let yourVC = self.storyboard?.instantiateViewController(withIdentifier: "yourViewController") as! yourViewController
    UIView.animate(withDuration: 0.75, animations: {() -> Void in
    UIView.setAnimationCurve(.easeInOut)
    self.navigationController?.pushViewController(terms, animated: true)
    UIView.setAnimationTransition(.flipFromRight, for: (self.navigationController?.view)!, cache: false)
    })

    Pop

    UIView.animate(withDuration: 0.75, animations: {() -> Void in
    UIView.setAnimationCurve(.easeInOut)
    UIView.setAnimationTransition(.flipFromLeft, for: (self.navigationController?.view)!, cache: false)
    })
    navigationController?.popViewController(animated: false)
  11. 5

    Aquí es cómo he hecho la misma en Swift:

    Para Empujar:

        UIView.animateWithDuration(0.75, animations: { () -> Void in
    UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut)
    self.navigationController!.pushViewController(nextView, animated: false)
    UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromRight, forView: self.navigationController!.view!, cache: false)
    })

    Pop:

    De hecho, me hice un poco diferente a algunas de las respuestas de arriba, pero como soy nuevo en rápido desarrollo, no podría ser de derecha. He reemplazado viewWillDisappear:animated: y se añade el pop-código no:

        UIView.animateWithDuration(0.75, animations: { () -> Void in
    UIView.setAnimationCurve(UIViewAnimationCurve.EaseInOut)
    UIView.setAnimationTransition(UIViewAnimationTransition.FlipFromLeft, forView: self.navigationController!.view, cache: false)
    })
    super.viewWillDisappear(animated)
  12. 5

    @Luca Davanzo la respuesta en Swift 4.2

    public extension UINavigationController {
    /**
    Pop current view controller to previous view controller.
    - parameter type:     transition animation type.
    - parameter duration: transition animation duration.
    */
    func pop(transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
    self.addTransition(transitionType: type, duration: duration)
    self.popViewController(animated: false)
    }
    /**
    Push a new view controller on the view controllers's stack.
    - parameter vc:       view controller to push.
    - parameter type:     transition animation type.
    - parameter duration: transition animation duration.
    */
    func push(viewController vc: UIViewController, transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
    self.addTransition(transitionType: type, duration: duration)
    self.pushViewController(vc, animated: false)
    }
    private func addTransition(transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
    let transition = CATransition()
    transition.duration = duration
    transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
    transition.type = type
    self.view.layer.add(transition, forKey: nil)
    }
    }
  13. 4

    Recientemente, yo estaba tratando de hacer algo similar. Decidí que no me guste el deslizamiento de la animación de la UINavigationController, pero también no quería hacer las animaciones que UIView da como curl o algo por el estilo. Yo quería hacer un cross fade entre los puntos de vista cuando me push o pop.

    El problema no consiste en el hecho de que la vista es, literalmente, la eliminación de la vista o hacer estallar una sobre la parte superior de la actual, por lo que un fade no funciona. La solución que se me vino a tomar mi nuevo punto de vista y añadiendo como una subvista a la actual vista superior en la UIViewController de la pila. Puedo añadir que con un alfa de 0, a continuación, hacer un fundido cruzado. Cuando la secuencia de animación acabados, empujo a la vista en la pila sin la animación de la misma. Yo, a continuación, volver a la vieja topView y limpiar las cosas que yo había cambiado.

    Es un poco más complicado que eso, porque usted tiene la navigationItems usted tiene que ajustar a hacer la transición correcta. Además, si haces cualquier rotación, entonces usted tiene que ajustar los tamaños de fotograma de como agregar los puntos de vista como subvistas para que se muestren correctamente en la pantalla. Aquí está una parte del código que he usado. Yo subclases de la UINavigationController y anuló el empuje y el pop de los métodos.

    -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
    UIViewController *currentViewController = [self.viewControllers lastObject];
    //if we don't have a current controller, we just do a normal push
    if(currentViewController == nil)
    {
    [super pushViewController:viewController animated:animated];
    return;
    }
    //if no animation was requested, we can skip the cross fade
    if(!animation)
    {
    [super pushViewController:viewController animated:NO];
    return;
    }
    //start the cross fade.  This is a tricky thing.  We basically add the new view
    //as a subview of the current view, and do a cross fade through alpha values.
    //then we push the new view on the stack without animating it, so it seemlessly is there.
    //Finally we remove the new view that was added as a subview to the current view.
    viewController.view.alpha = 0.0;
    //we need to hold onto this value, we'll be releasing it later
    NSString *title = [currentViewController.title retain];
    //add the view as a subview of the current view
    [currentViewController.view addSubview:viewController.view];
    [currentViewController.view bringSubviewToFront:viewController.view];
    UIBarButtonItem *rButtonItem = currentViewController.navigationItem.rightBarButtonItem;
    UIBarButtonItem *lButtonItem = currentViewController.navigationItem.leftBarButtonItem;
    NSArray *array = nil;
    //if we have a right bar button, we need to add it to the array, if not, we will crash when we try and assign it
    //so leave it out of the array we are creating to pass as the context.  I always have a left bar button, so I'm not checking to see if it is nil. Its a little sloppy, but you may want to be checking for the left BarButtonItem as well.
    if(rButtonItem != nil)
    array = [[NSArray alloc] initWithObjects:currentViewController,viewController,title,lButtonItem,rButtonItem,nil];
    else {
    array = [[NSArray alloc] initWithObjects:currentViewController,viewController,title,lButtonItem,nil];
    }
    //remove the right bar button for our transition
    [currentViewController.navigationItem setRightBarButtonItem:nil animated:YES];
    //remove the left bar button and create a backbarbutton looking item
    //[currentViewController.navigationItem setLeftBarButtonItem:nil animated:NO];
    //set the back button
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:title style:kButtonStyle target:self action:@selector(goBack)];
    [currentViewController.navigationItem setLeftBarButtonItem:backButton animated:YES];
    [viewController.navigationItem setLeftBarButtonItem:backButton animated:NO];
    [backButton release];
    [currentViewController setTitle:viewController.title];
    [UIView beginAnimations:@"push view" context:array];
    [UIView setAnimationDidStopSelector:@selector(animationForCrossFadePushDidStop:finished:context:)];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:0.80];
    [viewController.view setAlpha: 1.0];
    [UIView commitAnimations];
    }
    -(void)animationForCrossFadePushDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
    {
    UIViewController *c = [(NSArray*)context objectAtIndex:0];
    UIViewController *n = [(NSArray*)context objectAtIndex:1];
    NSString *title     = [(NSArray *)context objectAtIndex:2];
    UIBarButtonItem *l = [(NSArray *)context objectAtIndex:3];
    UIBarButtonItem *r = nil;
    //not all views have a right bar button, if we look for it and it isn't in the context,
    //we'll crash out and not complete the method, but the program won't crash.
    //So, we need to check if it is there and skip it if it isn't.
    if([(NSArray *)context count] == 5)
    r = [(NSArray *)context objectAtIndex:4];
    //Take the new view away from being a subview of the current view so when we go back to it
    //it won't be there anymore.
    [[[c.view subviews] lastObject] removeFromSuperview];
    [c setTitle:title];
    [title release];
    //set the search button
    [c.navigationItem setLeftBarButtonItem:l animated:NO];
    //set the next button
    if(r != nil)
    [c.navigationItem setRightBarButtonItem:r animated:NO];
    [super pushViewController:n animated:NO];
    }

    Como se menciono en el código, siempre tengo una izquierda botón de la barra de punto, así que no comprobar para ver si es nulo antes de ponerlo en la matriz que me pase como el contexto para la animación delegado. Si usted hace esto, usted puede querer hacer esa comprobación.

    El problema que encontré fue que si el bloqueo se produce en el método de delegado, que no se cuelgue el programa. Sólo detiene el delegado de completar, pero no recibe ningún tipo de advertencia.

    Así que ya me estaba haciendo a mi de limpieza en la que el delegado de la rutina, estaba causando un extraño comportamiento visual, ya que no estaba acabado la limpieza.

    El botón atrás puedo crear llamadas de un «goBack» método, y que el método sólo llama al pop de rutina.

    -(void)goBack
    { 
    [self popViewControllerAnimated:YES];
    }

    También, aquí está mi pop rutina.

    -(UIViewController *)popViewControllerAnimated:(BOOL)animated
    {
    //get the count for the number of viewControllers on the stack
    int viewCount = [[self viewControllers] count];
    //get the top view controller on the stack
    UIViewController *topViewController = [self.viewControllers objectAtIndex:viewCount - 1];
    //get the next viewController after the top one (this will be the new top one)
    UIViewController *newTopViewController = [self.viewControllers objectAtIndex:viewCount - 2];
    //if no animation was requested, we can skip the cross fade
    if(!animated)
    {
    [super popViewControllerAnimated:NO];
    return topViewController;
    }
    //start of the cross fade pop.  A bit tricky.  We need to add the new top controller
    //as a subview of the curent view controler with an alpha of 0.  We then do a cross fade.
    //After that we pop the view controller off the stack without animating it.
    //Then the cleanup happens: if the view that was popped is not released, then we
    //need to remove the subview we added and change some titles back.
    newTopViewController.view.alpha = 0.0;
    [topViewController.view addSubview:newTopViewController.view];
    [topViewController.view bringSubviewToFront:newTopViewController.view];
    NSString *title = [topViewController.title retain];
    UIBarButtonItem *lButtonItem = topViewController.navigationItem.leftBarButtonItem;
    UIBarButtonItem *rButtonItem = topViewController.navigationItem.rightBarButtonItem;
    //set the new buttons on top of the current controller from the new top controller
    if(newTopViewController.navigationItem.leftBarButtonItem != nil)
    {
    [topViewController.navigationItem setLeftBarButtonItem:newTopViewController.navigationItem.leftBarButtonItem animated:YES];
    }
    if(newTopViewController.navigationItem.rightBarButtonItem != nil)
    {
    [topViewController.navigationItem setRightBarButtonItem:newTopViewController.navigationItem.rightBarButtonItem animated:YES];
    }
    [topViewController setTitle:newTopViewController.title];
    //[topViewController.navigationItem.leftBarButtonItem setTitle:newTopViewController.navigationItem.leftBarButtonItem.title];
    NSArray *array = nil;
    if(rButtonItem != nil)
    array = [[NSArray alloc] initWithObjects:topViewController,title,lButtonItem,rButtonItem,nil];
    else {
    array = [[NSArray alloc] initWithObjects:topViewController,title,lButtonItem,nil];
    }
    [UIView beginAnimations:@"pop view" context:array];
    [UIView setAnimationDidStopSelector:@selector(animationForCrossFadePopDidStop:finished:context:)];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:0.80];
    [newTopViewController.view setAlpha: 1.0];
    [UIView commitAnimations];
    return topViewController;
    }
    -(void)animationForCrossFadePopDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
    {
    UIViewController *c = [(NSArray *)context objectAtIndex:0];
    //UIViewController *n = [(NSArray *)context objectAtIndex:1];
    NSString *title = [(NSArray *)context objectAtIndex:1];
    UIBarButtonItem *l = [(NSArray *)context objectAtIndex:2];
    UIBarButtonItem *r = nil;
    //Not all views have a right bar button.  If we look for one that isn't there
    //we'll crash out and not complete this method, but the program will continue.
    //So we need to check if it is therea nd skip it if it isn't.
    if([(NSArray *)context count] == 4)
    r = [(NSArray *)context objectAtIndex:3];
    //pop the current view from the stack without animation
    [super popViewControllerAnimated:NO];
    //if what was the current veiw controller is not nil, then lets correct the changes
    //we made to it.
    if(c != nil)
    {
    //remove the subview we added for the transition
    [[c.view.subviews lastObject] removeFromSuperview];
    //reset the title we changed
    c.title = title;
    [title release];
    //replace the left bar button that we changed
    [c.navigationItem setLeftBarButtonItem:l animated:NO];
    //if we were passed a right bar button item, replace that one as well
    if(r != nil)
    [c.navigationItem setRightBarButtonItem:r animated:NO];
    else {
    [c.navigationItem setRightBarButtonItem:nil animated:NO];
    }
    }
    }

    Que eso es todo. Usted necesitará un código adicional si desea implementar rotaciones. Tendrás que ajustar el tamaño del marco de sus puntos de vista que agregue como subvistas antes de mostrar de lo contrario tendremos problemas de la orientación es horizontal, pero la última vez que vieron a la vista anterior fue el retrato. Así que, a continuación, se agrega como una sub vista y difuminar, pero se muestra como retrato, entonces, al pop sin animación, el mismo punto de vista, pero el que está en la pila, ahora es el paisaje. La cosa entera se parece un poco a la moda. Todo el mundo de la implementación de la rotación es un poco diferente, por eso no incluí mi código para que aquí.

    Esperanza que ayuda a algunas personas. He mirado por todas partes para algo como esto, y no podía encontrar nada. No creo que esta es la respuesta perfecta, pero está trabajando muy bien para mí en este momento.

    • Mientras admirable, esto es, honestamente, no es la solución ahora, 7 años más tarde!
    • Estás en lo correcto. Esta respuesta fue a partir de 2011. Se trabajó en aquel entonces, pero las cosas han cambiado mucho desde entonces. =)
  14. 4

    Ahora puede utilizar UIView.transition. Tenga en cuenta que animated:false. Esto funciona con cualquier opción transición, pop, push, o reemplazar la pila.

    if let nav = self.navigationController
    {
    UIView.transition(with:nav.view, duration:0.3, options:.transitionCrossDissolve, animations: {
    _ = nav.popViewController(animated:false)
    }, completion:nil)
    }
  15. 3

    Utilizando iJordan la respuesta como fuente de inspiración, ¿por qué no simplemente crear una Categoría en la UINavigationController para uso de toda la aplicación en lugar de copiar/pegar este código de animación por todo el lugar?

    UINavigationController+Animación.h

    @interface UINavigationController (Animation)
    - (void) pushViewControllerWithFlip:(UIViewController*) controller;
    - (void) popViewControllerWithFlip;
    @end

    UINavigationController+Animación.m

    @implementation UINavigationController (Animation)
    - (void) pushViewControllerWithFlip:(UIViewController *) controller
    {
    [UIView animateWithDuration:0.50
    animations:^{
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [self pushViewController:controller animated:NO];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
    }];
    }
    - (void) popViewControllerWithFlip
    {
    [UIView animateWithDuration:0.5
    animations:^{
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
    }];
    [self popViewControllerAnimated:NO];
    }
    @end

    A continuación, sólo tiene que importar el UINavigationController+Animación.h archivo y lo llaman normalmente:

    [self.navigationController pushViewControllerWithFlip:[[NewViewController alloc] init]];
    [self.navigationController popViewControllerWithFlip];
    • Inteligente. Pero, ¿por qué no añadir push/pop métodos que tienen un argumento de UIViewAnimationTransition en lugar de codificar a flipFromRight ?
    • estos son métodos de conveniencia – de esta manera, el implementador no es necesario recordar que UIViewAnimationTransition valor para pasar específicos para cada tipo de animación, que acaba de llamar al método con el «inglés» nombre de lo que quieren lograr.
    • también, su sugerencia es sin duda válido – si yo fuera aún usando objective-c y necesarios para el soporte de muchos estilos de transición (definitivamente no se recomienda como muchos diferentes estilos de transición se va a confundir a los usuarios) me hubiera 1 método que toma el UIViewAnimationTransition tipo, luego de varios métodos de conveniencia para que el desarrollo sea más fácil.
  16. 2

    Echar un vistazo a ADTransitionController, una gota en el reemplazo para UINavigationController personalizados con animaciones de transición (su API coincide con la API de UINavigationController) que hemos creado en Applidium.

    Puede utilizar diferentes pre-definido animaciones para empuje y pop acciones tales como Pase, Fade, Cubo, Carrusel, Zoom y así sucesivamente.

  17. 2

    Mientras que todas las respuestas aquí son grandes y la mayoría funcionan muy bien, hay un poco más simple método que logra el mismo efecto…

    Para Empujar:

      NextViewController *nextViewController = [[NextViewController alloc] init];
    //Shift the view to take the status bar into account 
    CGRect frame = nextViewController.view.frame;
    frame.origin.y -= 20;
    frame.size.height += 20;
    nextViewController.view.frame = frame;
    [UIView transitionFromView:self.navigationController.topViewController.view toView:nextViewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromRight completion:^(BOOL finished) {
    [self.navigationController pushViewController:nextViewController animated:NO];
    }];

    Pop:

      int numViewControllers = self.navigationController.viewControllers.count;
    UIView *nextView = [[self.navigationController.viewControllers objectAtIndex:numViewControllers - 2] view];
    [UIView transitionFromView:self.navigationController.topViewController.view toView:nextView duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
    [self.navigationController popViewControllerAnimated:NO];
    }];}
    • Este se bloqueará cuando se poping a raíz de controlador de vista.
    • Estás en lo correcto. Mis suposiciones son incorrectas. Disculpas.
  18. 2

    Es muy simple

    self.navigationController?.view.semanticContentAttribute = .forceRightToLeft
    • Bienvenido a StackOverflow: si código postal, XML o muestras de datos, por favor, destacar las líneas en el editor de texto y haga clic en el «código de las muestras» botón ( { } ) en la barra de herramientas del editor o el uso de Ctrl+K en el teclado para bien el formato y la sintaxis resaltar!
  19. 1

    Ver mi respuesta a esta pregunta una manera de hacerlo en mucho menos líneas de código. Este método le permite animar un pseudo-«Push» de un nuevo controlador de vista de cualquier forma que te gusta, y cuando la animación se hace en ella se establece la Navegación Controlador como si se hubiera utilizado el estándar método Push. Mi ejemplo permite animar una diapositiva de la izquierda o de la derecha.
    Código repetido aquí por conveniencia:

    -(void) showVC:(UIViewController *) nextVC rightToLeft:(BOOL) rightToLeft {
    [self addChildViewController:neighbor];
    CGRect offscreenFrame = self.view.frame;
    if(rightToLeft) {
    offscreenFrame.origin.x = offscreenFrame.size.width * -1.0;
    } else if(direction == MyClimbDirectionRight) {
    offscreenFrame.origin.x = offscreenFrame.size.width;
    }
    [[neighbor view] setFrame:offscreenFrame];
    [self.view addSubview:[neighbor view]];
    [neighbor didMoveToParentViewController:self];
    [UIView animateWithDuration:0.5 animations:^{
    [[neighbor view] setFrame:self.view.frame];
    } completion:^(BOOL finished){
    [neighbor willMoveToParentViewController:nil];
    [neighbor.view removeFromSuperview];
    [neighbor removeFromParentViewController];
    [[self navigationController] pushViewController:neighbor animated:NO];
    NSMutableArray *newStack = [[[self navigationController] viewControllers] mutableCopy];
    [newStack removeObjectAtIndex:1]; //self, just below top
    [[self navigationController] setViewControllers:newStack];
    }];
    }
  20. 0

    Yo no soy consciente de ningún modo se puede cambiar la animación de transición públicamente.

    Si el botón «atrás» no es necesario que usted debe uso modal de vista de los controladores tener el «empuje de abajo» /»flip» /»fade» /(≥3.2)»doblez de página» transiciones.


    Sobre la privado lado, el método de -pushViewController:animated: llamadas a los indocumentados método -pushViewController:transition:forceImmediate:, así por ejemplo, si desea un flip-de-izquierda-a-derecha de transición, puede utilizar

    [navCtrler pushViewController:ctrler transition:10 forceImmediate:NO];

    No se puede cambiar el «pop» de la transición de esta manera, sin embargo.

  21. 0

    De la aplicación de ejemplo, echa un vistazo a esta variación.
    https://github.com/mpospese/MPFoldTransition/

    #pragma mark - UINavigationController(MPFoldTransition)
    @implementation UINavigationController(MPFoldTransition)
    //- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
    - (void)pushViewController:(UIViewController *)viewController foldStyle:(MPFoldStyle)style
    {
    [MPFoldTransition transitionFromViewController:[self visibleViewController] 
    toViewController:viewController 
    duration:[MPFoldTransition defaultDuration]  
    style:style 
    completion:^(BOOL finished) {
    [self pushViewController:viewController animated:NO];
    }
    ];
    }
    - (UIViewController *)popViewControllerWithFoldStyle:(MPFoldStyle)style
    {
    UIViewController *toController = [[self viewControllers] objectAtIndex:[[self viewControllers] count] - 2];
    [MPFoldTransition transitionFromViewController:[self visibleViewController] 
    toViewController:toController 
    duration:[MPFoldTransition defaultDuration] 
    style:style
    completion:^(BOOL finished) {
    [self popViewControllerAnimated:NO];
    }
    ];
    return toController;
    }
  22. 0

    Sólo tiene que utilizar:

    ViewController *viewController = [[ViewController alloc] init];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
    navController.navigationBarHidden = YES;
    [self presentViewController:navController animated:YES completion: nil];
    [viewController release];
    [navController release];
  23. 0

    Darse cuenta de que esta es una vieja cuestión. Aun así me gustaría publicar esta respuesta, ya que he tenido algunos problemas de popping varios viewControllers con la propuesta de respuestas. Mi solución es subclase UINavigationController y reemplazar todo el pop y push métodos.

    FlippingNavigationController.h

    @interface FlippingNavigationController : UINavigationController
    @end

    FlippingNavigationController.m:

    #import "FlippingNavigationController.h"
    #define FLIP_DURATION 0.5
    @implementation FlippingNavigationController
    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
    [UIView transitionWithView:self.view
    duration:animated?FLIP_DURATION:0
    options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromRight
    animations:^{ [super pushViewController:viewController
    animated:NO]; }
    completion:nil];
    }
    - (UIViewController *)popViewControllerAnimated:(BOOL)animated
    {
    return [[self popToViewController:[self.viewControllers[self.viewControllers.count - 2]]
    animated:animated] lastObject];
    }
    - (NSArray *)popToRootViewControllerAnimated:(BOOL)animated
    {
    return [self popToViewController:[self.viewControllers firstObject]
    animated:animated];
    }
    - (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
    __block NSArray* viewControllers = nil;
    [UIView transitionWithView:self.view
    duration:animated?FLIP_DURATION:0
    options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionFlipFromLeft
    animations:^{ viewControllers = [super popToViewController:viewController animated:NO]; }
    completion:nil];
    return viewControllers;
    }
    @end
  24. 0

    Sé que este hilo es viejo, pero yo pensé que había puesto en mis dos centavos. Usted no necesita hacer una animación personalizada, hay una sencilla (tal vez chapucero) forma de hacerlo. En lugar de usar empuje, crear un nuevo controlador de navegación, hacer que el nuevo controlador de vista de la raíz de controlador de vista de que nav controlador y, a continuación, presentar el nav controlador de la original nav controlador. El presente es fácilmente personalizable con muchos estilos, y no hay necesidad de hacer una animación personalizada.

    Por ejemplo:

    UIViewcontroller viewControllerYouWantToPush = UIViewController()
    UINavigationController newNavController = UINavigationController(root: viewControllerYouWantToView)
    newNavController.navBarHidden = YES;
    self.navigationController.present(newNavController)

    Y usted puede cambiar el estilo de presentación que usted desee.

  25. -1

    Me encontré con un leve recursiva forma de hacerlo que funcione para mis propósitos. Tengo una variable de instancia de tipo BOOL que puedo usar para bloquear el normal estallar la animación y el sustituto de mi propia no animados pop mensaje. La variable se establece inicialmente a NO. Cuando el botón se pulsa, el delegado método se establece para SÍ y envía un nuevo no-animado pop mensaje a la barra de navegación, por lo tanto, llamar el mismo método delegado de nuevo, esta vez con la variable se establece en SÍ. Con la variable se establece en SÍ, el delegado método establece que NO y vuelve en SÍ para permitir que los no animados pop ocurrir. Después de la segunda llamada a delegado devuelve, terminamos de nuevo en la primera, donde NO se devuelve, el bloqueo de la animación original de pop! En realidad no es tan complicado como suena. Mi shouldPopItem método se parece a esto:

    - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item 
    {
    if ([[navigationBar items] indexOfObject:item] == 1) 
    {
    [expandedStack restack];    
    }
    if (!progPop) 
    {
    progPop = YES;
    [navBar popNavigationItemAnimated:NO];
    return NO;
    }
    else 
    {
    progPop = NO;
    return YES;
    }
    }

    Funciona para mí.

Dejar respuesta

Please enter your comment!
Please enter your name here