Estoy usando presentViewController para presentar una nueva pantalla
let dashboardWorkout = DashboardWorkoutViewController()
presentViewController(dashboardWorkout, animated: true, completion: nil)
Esto presenta una nueva pantalla de abajo hacia arriba, pero quiero que se presente de derecha a izquierda sin usar UINavigationController
.
Estoy usando Xib en lugar del guión gráfico, ¿cómo puedo hacer eso?
Respuestas:
No importa si lo es
xib
o lostoryboard
que estás usando. Normalmente, la transición de derecha a izquierda se usa cuando empuja un controlador de vista al de presentadorUINavigiationController
.ACTUALIZAR
Función de sincronización agregada
kCAMediaTimingFunctionEaseInEaseOut
Proyecto de muestra con implementación de Swift 4 agregada a GitHub
Swift 3 y 4.2
let transition = CATransition() transition.duration = 0.5 transition.type = CATransitionType.push transition.subtype = CATransitionSubtype.fromRight transition.timingFunction = CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut) view.window!.layer.add(transition, forKey: kCATransition) present(dashboardWorkout, animated: false, completion: nil)
ObjC
CATransition *transition = [[CATransition alloc] init]; transition.duration = 0.5; transition.type = kCATransitionPush; transition.subtype = kCATransitionFromRight; [transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; [self.view.window.layer addAnimation:transition forKey:kCATransition]; [self presentViewController:dashboardWorkout animated:false completion:nil];
Rápido 2.x
let transition = CATransition() transition.duration = 0.5 transition.type = kCATransitionPush transition.subtype = kCATransitionFromRight transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut) view.window!.layer.addAnimation(transition, forKey: kCATransition) presentViewController(dashboardWorkout, animated: false, completion: nil)
Parece que el
animated
parámetro en elpresentViewController
método realmente no importa en este caso de transición personalizada. Puede tener cualquier valor, ya seatrue
ofalse
.fuente
Código completo para presentar / despedir, Swift 3
extension UIViewController { func presentDetail(_ viewControllerToPresent: UIViewController) { let transition = CATransition() transition.duration = 0.25 transition.type = kCATransitionPush transition.subtype = kCATransitionFromRight self.view.window!.layer.add(transition, forKey: kCATransition) present(viewControllerToPresent, animated: false) } func dismissDetail() { let transition = CATransition() transition.duration = 0.25 transition.type = kCATransitionPush transition.subtype = kCATransitionFromLeft self.view.window!.layer.add(transition, forKey: kCATransition) dismiss(animated: false) } }
fuente
Lee todas las respuestas y no veo la solución correcta. La forma correcta de hacerlo es hacer UIViewControllerAnimatedTransitioning personalizado para el delegado de VC presentado.
Por lo tanto, se supone que se deben realizar más pasos, pero el resultado es más personalizable y no tiene efectos secundarios, como pasar de la vista junto con la vista presentada.
Entonces, suponga que tiene algún ViewController, y hay un método para presentar
var presentTransition: UIViewControllerAnimatedTransitioning? var dismissTransition: UIViewControllerAnimatedTransitioning? func showSettings(animated: Bool) { let vc = ... create new vc to present presentTransition = RightToLeftTransition() dismissTransition = LeftToRightTransition() vc.modalPresentationStyle = .custom vc.transitioningDelegate = self present(vc, animated: true, completion: { [weak self] in self?.presentTransition = nil }) }
presentTransition
ydismissTransition
se utiliza para animar sus controladores de vista. Entonces adopta su ViewController paraUIViewControllerTransitioningDelegate
:extension ViewController: UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return presentTransition } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return dismissTransition } }
Entonces, el último paso es crear su transición personalizada:
class RightToLeftTransition: NSObject, UIViewControllerAnimatedTransitioning { let duration: TimeInterval = 0.25 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return duration } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let container = transitionContext.containerView let toView = transitionContext.view(forKey: .to)! container.addSubview(toView) toView.frame.origin = CGPoint(x: toView.frame.width, y: 0) UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: { toView.frame.origin = CGPoint(x: 0, y: 0) }, completion: { _ in transitionContext.completeTransition(true) }) } } class LeftToRightTransition: NSObject, UIViewControllerAnimatedTransitioning { let duration: TimeInterval = 0.25 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return duration } func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let container = transitionContext.containerView let fromView = transitionContext.view(forKey: .from)! container.addSubview(fromView) fromView.frame.origin = .zero UIView.animate(withDuration: duration, delay: 0, options: .curveEaseIn, animations: { fromView.frame.origin = CGPoint(x: fromView.frame.width, y: 0) }, completion: { _ in fromView.removeFromSuperview() transitionContext.completeTransition(true) }) } }
En ese controlador de vista de código que se presenta sobre el contexto actual, puede realizar sus personalizaciones desde ese punto. También puede ver que la costumbre también
UIPresentationController
es útil (pase en el usoUIViewControllerTransitioningDelegate
)fuente
También puede utilizar segue personalizado.
Rápido 5
class SegueFromRight: UIStoryboardSegue { override func perform() { let src = self.source let dst = self.destination src.view.superview?.insertSubview(dst.view, aboveSubview: src.view) dst.view.transform = CGAffineTransform(translationX: src.view.frame.size.width, y: 0) UIView.animate(withDuration: 0.25, delay: 0.0, options: UIView.AnimationOptions.curveEaseInOut, animations: { dst.view.transform = CGAffineTransform(translationX: 0, y: 0) }, completion: { finished in src.present(dst, animated: false, completion: nil) }) } }
fuente
Prueba esto,
let animation = CATransition() animation.duration = 0.5 animation.type = kCATransitionPush animation.subtype = kCATransitionFromRight animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) vc.view.layer.addAnimation(animation, forKey: "SwitchToView") self.presentViewController(vc, animated: false, completion: nil)
Aquí
vc
está viewcontroller,dashboardWorkout
en su caso.fuente
Si desea utilizar el método de transición CAT de "solución rápida" ...
class AA: UIViewController func goToBB { let bb = .. instantiateViewcontroller, storyboard etc .. as! AlreadyOnboardLogin let tr = CATransition() tr.duration = 0.25 tr.type = kCATransitionMoveIn // use "MoveIn" here tr.subtype = kCATransitionFromRight view.window!.layer.add(tr, forKey: kCATransition) present(bb, animated: false) bb.delegate, etc = set any other needed values }
y entonces ...
func dismissingBB() { let tr = CATransition() tr.duration = 0.25 tr.type = kCATransitionReveal // use "Reveal" here tr.subtype = kCATransitionFromLeft view.window!.layer.add(tr, forKey: kCATransition) dismiss(self) .. or dismiss(bb), or whatever }
Desafortunadamente, todo esto no es realmente correcto :(
CATransition
realmente no está hecho para hacer este trabajo.Tenga en cuenta que obtendrá el molesto fundido cruzado a negro que, lamentablemente, arruina el efecto.
A muchos desarrolladores (como yo) realmente no les gusta usar
NavigationController
. A menudo, es más flexible presentar simplemente de manera ad-hoc sobre la marcha, especialmente para aplicaciones inusuales y complejas. Sin embargo, no es difícil "agregar" un controlador de navegación.simplemente en el guión gráfico, vaya a la entrada VC y haga clic en "incrustar -> en el controlador de navegación". Realmente eso es todo. O,
en
didFinishLaunchingWithOptions
es fácil de construir su controlador de navegación si lo prefiererealmente ni siquiera necesita mantener la variable en cualquier lugar, ya
.navigationController
que siempre está disponible como propiedad, fácil.Realmente, una vez que tienes un navigationController, es trivial hacer transiciones entre pantallas,
let nextScreen = instantiateViewController etc as! NextScreen navigationController? .pushViewController(nextScreen, animated: true)
y tu puedes
pop
.Sin embargo, eso solo le da el efecto estándar de "doble empuje" de Apple ...
(El viejo se desliza a menor velocidad, mientras que el nuevo se desliza).
En general, y sorprendentemente, normalmente debe hacer el esfuerzo de realizar una transición personalizada completa.
Incluso si solo desea la transición más simple, más común, pasar / salir, tiene que hacer una transición personalizada completa.
Afortunadamente, para hacer eso, hay un código repetitivo de cortar y pegar en este control de calidad ... https://stackoverflow.com/a/48081504/294884 . ¡Feliz año nuevo 2018!
fuente
importar UIKit y crear una extensión para UIViewController:
extension UIViewController { func transitionVc(vc: UIViewController, duration: CFTimeInterval, type: CATransitionSubtype) { let customVcTransition = vc let transition = CATransition() transition.duration = duration transition.type = CATransitionType.push transition.subtype = type transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) view.window!.layer.add(transition, forKey: kCATransition) present(customVcTransition, animated: false, completion: nil) }}
después de una llamada simple:
let vC = YourViewController() transitionVc(vc: vC, duration: 0.5, type: .fromRight)
de izquierda a derecha:
let vC = YourViewController() transitionVc(vc: vC, duration: 0.5, type: .fromleft)
puede cambiar la duración con su duración preferida ...
fuente
Prueba esto.
let transition: CATransition = CATransition() transition.duration = 0.3 transition.type = kCATransitionReveal transition.subtype = kCATransitionFromLeft self.view.window!.layer.addAnimation(transition, forKey: nil) self.dismissViewControllerAnimated(false, completion: nil)
fuente
let transition = CATransition() transition.duration = 0.25 transition.type = kCATransitionPush transition.subtype = kCATransitionFromLeft transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) tabBarController?.view.layer.add(transition, forKey: kCATransition) self.navigationController?.popToRootViewController(animated: true)
fuente
Presentar el controlador de vista de derecha a izquierda en iOS usando Swift
func FrkTransition() { let transition = CATransition() transition.duration = 2 transition.type = kCATransitionPush transitioningLayer.add(transition,forKey: "transition") // Transition to "blue" state transitioningLayer.backgroundColor = UIColor.blue.cgColor transitioningLayer.string = "Blue" }
Referencia de: [ https://developer.apple.com/documentation/quartzcore/catransition][1]
fuente
Tengo una mejor solución que me ha funcionado si quieres mantener la animación clásica de Apple, sin ver esa transición "negra" que ves usando CATransition (). Simplemente use el método popToViewController.
Puede buscar el viewController que necesita en
self.navigationController.viewControllers // Array of VC that contains all VC of current stack
Puede buscar el viewController que necesita buscando su restoreIdentifier.
TENGA CUIDADO: por ejemplo, si está navegando a través de 3 controles de vista, y cuando llega al último, desea abrir el primero. En este caso, perderá la referencia al SEGUNDO controlador de vista efectivo porque el popToViewController lo ha sobrescrito. Por cierto, hay una solución: puede guardar fácilmente antes del popToViewcontroller, el VC que necesitará más adelante. Me funcionó muy bien.
fuente
Esto funcionó para mí:
self.navigationController?.pushViewController(controller, animated: true)
fuente