Я использую PresentViewController для отображения нового экрана
let dashboardWorkout = DashboardWorkoutViewController()
presentViewController(dashboardWorkout, animated: true, completion: nil)
Это представляет новый экран снизу вверх, но я хочу, чтобы он отображался справа налево без использования UINavigationController
.
Я использую Xib вместо раскадровки, как я могу это сделать?
Ответы:
Неважно, используете ли вы его
xib
илиstoryboard
используете. Обычно переход справа налево используется, когда вы вставляете контроллер представления в презентациюUINavigiationController
.ОБНОВИТЬ
Добавлена функция тайминга
kCAMediaTimingFunctionEaseInEaseOut
Пример проекта с реализацией Swift 4 добавлен на GitHub
Swift 3 и 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];
Swift 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)
Похоже, что
animated
параметр вpresentViewController
методе не имеет значения в этом случае пользовательского перехода. Это может быть любое значение, либоtrue
илиfalse
.источник
Полный код для подарка / увольнения, 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) } }
источник
Прочтите все ответы и не увидите правильного решения. Правильный способ сделать это - создать собственный UIViewControllerAnimatedTransitioning для представленного делегата VC.
Таким образом, предполагается, что нужно сделать больше шагов, но результат более настраиваемый и не имеет побочных эффектов, таких как переход из представления вместе с представленным представлением.
Итак, предположим, что у вас есть ViewController и есть метод для представления
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
иdismissTransition
используется для анимации ваших контроллеров представления. Итак, вы адаптируете свой ViewController дляUIViewControllerTransitioningDelegate
:extension ViewController: UIViewControllerTransitioningDelegate { func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return presentTransition } func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return dismissTransition } }
Итак, последний шаг - создать собственный переход:
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) }) } }
В этом контроллере представления кода представлен в текущем контексте, вы можете сделать свои настройки с этого момента. Также вы можете увидеть, что пользовательские
UIPresentationController
настройки тоже полезны (переходите к использованиюUIViewControllerTransitioningDelegate
)источник
Вы также можете использовать пользовательский переход.
Swift 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) }) } }
источник
Попробуй это,
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)
Вот
vc
это ViewController,dashboardWorkout
в вашем случае.источник
Если вы действительно хотите использовать метод CATransition "быстрого исправления" ....
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 }
а потом ...
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 }
К сожалению, все это не совсем правильно :(
CATransition
на самом деле не предназначен для этой работы.Обратите внимание, что вы получите раздражающий переход к черному, который, к сожалению, испортит эффект.
Многие разработчики (например, я) действительно не любят использовать
NavigationController
. Часто бывает более гибким просто представлять в специальной манере, особенно для необычных и сложных приложений. Однако «добавить» навигационный контроллер несложно.просто в раскадровке перейдите к записи VC и нажмите «встроить -> в контроллер навигации». На самом деле все. Или же,
в
didFinishLaunchingWithOptions
нем легко собрать свой навигационный контроллер, если вы предпочитаетевам даже не нужно нигде хранить переменную, поскольку
.navigationController
она всегда доступна как свойство - легко.На самом деле, когда у вас есть navigationController, переходы между экранами тривиальны,
let nextScreen = instantiateViewController etc as! NextScreen navigationController? .pushViewController(nextScreen, animated: true)
и можно
pop
.Однако это дает вам только стандартный яблочный эффект "двойного нажатия" ...
(Старый соскальзывает с меньшей скоростью, так как новый скользит.)
Как правило, что удивительно, вам обычно приходится прилагать усилия, чтобы выполнить полностью настраиваемый переход.
Даже если вам просто нужен самый простой, наиболее распространенный переход при перемещении / выводе, вам все же необходимо выполнить полностью настраиваемый переход.
К счастью, для этого в этом QA есть вырезанный и вставленный шаблонный код ... https://stackoverflow.com/a/48081504/294884 . С новым 2018 годом!
источник
импортировать UIKit и создать одно расширение для 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) }}
после простого вызова:
let vC = YourViewController() transitionVc(vc: vC, duration: 0.5, type: .fromRight)
слева направо:
let vC = YourViewController() transitionVc(vc: vC, duration: 0.5, type: .fromleft)
вы можете изменить продолжительность на желаемую продолжительность ...
источник
Попробуй это.
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)
источник
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)
источник
представить контроллер представления справа налево в iOS с помощью 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" }
Ссылка Автор: [ https://developer.apple.com/documentation/quartzcore/catransition visible [1 ]
источник
У меня есть лучшее решение, которое сработало для меня, если вы хотите сохранить классическую анимацию Apple, не видя того «черного» перехода, который вы видите с помощью CATransition (). Просто используйте метод popToViewController.
Вы можете найти нужный вам viewController в
self.navigationController.viewControllers // Array of VC that contains all VC of current stack
Вы можете найти нужный вам viewController, выполнив поиск по его recoveryIdentifier.
БУДЬТЕ ОСТОРОЖНЫ: например, если вы перемещаетесь по 3 контроллерам представлений, и когда вы переходите к последнему, вы хотите открыть первый. В этом случае вы потеряете ссылку на эффективный ВТОРОЙ контроллер представления, потому что popToViewController перезаписал его. Кстати, есть решение: вы можете легко сохранить до popToViewcontroller, VC вам понадобится позже. У меня это сработало очень хорошо.
источник
Это сработало для меня:
self.navigationController?.pushViewController(controller, animated: true)
источник