При добавлении нового контроллера в стек навигации:
self.navigationController!.pushViewController(PushedViewController(), animated: true)
он появляется справа:
Как изменить направление анимации, чтобы оно отображалось слева?
При добавлении нового контроллера в стек навигации:
self.navigationController!.pushViewController(PushedViewController(), animated: true)
он появляется справа:
Как изменить направление анимации, чтобы оно отображалось слева?
Swift 5.1: переход с разных сторон
Вот простое расширение для разных направлений. (Проверено в Swift 5)
Похоже, вы хотите использовать segueFromLeft(). Я добавил и другие примеры.
extension CATransition {
//New viewController will appear from bottom of screen.
func segueFromBottom() -> CATransition {
self.duration = 0.375 //set the duration to whatever you'd like.
self.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.type = CATransitionType.moveIn
self.subtype = CATransitionSubtype.fromTop
return self
}
//New viewController will appear from top of screen.
func segueFromTop() -> CATransition {
self.duration = 0.375 //set the duration to whatever you'd like.
self.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.type = CATransitionType.moveIn
self.subtype = CATransitionSubtype.fromBottom
return self
}
//New viewController will appear from left side of screen.
func segueFromLeft() -> CATransition {
self.duration = 0.1 //set the duration to whatever you'd like.
self.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.type = CATransitionType.moveIn
self.subtype = CATransitionSubtype.fromLeft
return self
}
//New viewController will pop from right side of screen.
func popFromRight() -> CATransition {
self.duration = 0.1 //set the duration to whatever you'd like.
self.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.type = CATransitionType.reveal
self.subtype = CATransitionSubtype.fromRight
return self
}
//New viewController will appear from left side of screen.
func popFromLeft() -> CATransition {
self.duration = 0.1 //set the duration to whatever you'd like.
self.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
self.type = CATransitionType.reveal
self.subtype = CATransitionSubtype.fromLeft
return self
}
}
А вот как вы реализуете указанное расширение:
let nav = self.navigationController //grab an instance of the current navigationController
DispatchQueue.main.async { //make sure all UI updates are on the main thread.
nav?.view.layer.add(CATransition().segueFromLeft(), forKey: nil)
nav?.pushViewController(YourViewController(), animated: false)
}
let obj = self.storyboard?.instantiateViewController(withIdentifier: "ViewController")as! ViewController
let transition:CATransition = CATransition()
transition.duration = 0.3
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
self.navigationController!.view.layer.add(transition, forKey: kCATransition)
self.navigationController?.pushViewController(obj, animated: true)
Когда вы используете popToViewController, время
transition.subtype = kCATransitionFromRight
Я использовал Hero в качестве решения.
import Hero
Затем в том месте, где вы собираетесь показать новый UIViewController, включите анимацию по умолчанию:
Hero.shared.defaultAnimation = HeroDefaultAnimationType.cover(direction: .right)
Также укажите, что ваш UINavigationController будет использовать библиотеку Hero:
self.navigationController?.hero.isEnabled = true
После этого вы получите ожидаемый результат, даже если вы используете стандартную функцию pushViewController:
self.navigationController?.pushViewController(vc, animated: true)
Вам нужно будет написать свою собственную процедуру перехода для достижения ваших потребностей.
DOCS от Apple:
https://developer.apple.com/documentation/uikit/uiviewcontrollercontexttransitioning
Статья:
Хорошо, здесь вы найдете решение для вас. Добавьте файл с именем LeftToRightTransitionProxy.swift
со следующим контентом
import UIKit
final class LeftToRightTransitionProxy: NSObject {
func setup(with controller: UINavigationController) {
controller.delegate = self
}
}
extension LeftToRightTransitionProxy: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if operation == .push {
return AnimationController(direction: .forward)
} else {
return AnimationController(direction: .backward)
}
}
}
private final class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {
enum Direction {
case forward, backward
}
let direction: Direction
init(direction: Direction) {
self.direction = direction
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 0.3
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let toView = transitionContext.view(forKey: .to),
let fromView = transitionContext.view(forKey: .from) else {
return
}
let container = transitionContext.containerView
container.addSubview(toView)
let initialX: CGFloat
switch direction {
case .forward: initialX = -fromView.bounds.width
case .backward: initialX = fromView.bounds.width
}
toView.frame = CGRect(origin: CGPoint(x: initialX, y: 0), size: toView.bounds.size)
let animation: () -> Void = {
toView.frame = CGRect(origin: .zero, size: toView.bounds.size)
}
let completion: (Bool) -> Void = { _ in
let success = !transitionContext.transitionWasCancelled
if !success {
toView.removeFromSuperview()
}
transitionContext.completeTransition(success)
}
UIView.animate(
withDuration: transitionDuration(using: transitionContext),
animations: animation,
completion: completion
)
}
}
И вот как вы можете это использовать:
final class ViewController: UIViewController {
let animationProxy = LeftToRightTransitionProxy()
override func viewDidLoad() {
super.viewDidLoad()
animationProxy.setup(with: navigationController!)
}
}
Это решение обеспечивает анимацию для направления вперед и назад (push
и pop
). Это можно управлять navigationController(_:animationControllerFor:from:to:)
методы вашего LeftToRightTransitionProxy
класса (просто возвращает nil
, чтобы удалить анимацию).
Если вам нужно это поведение для определенного подкласса UIViewController
поместите соответствующие проверки в метод navigationController(_:animationControllerFor:from:to:)
:
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if operation == .push && toVC is DetailViewController {
return AnimationController(direction: .forward)
} else if operation == .pop && toVC is ViewController {
return AnimationController(direction: .backward)
}
return nil
}
Это может помочь вам
let nextVc = self.storyboard?.instantiateViewController(withIdentifier: "nextVc")
let transition = CATransition()
transition.duration = 0.5
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromLeft
transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
self.navigationController?.pushViewController(nextVc!, animated: false)
Если вы хотите узнать, как выполнять пользовательские переходы (например, представление справа налево), то это довольно хороший учебник для их настройки.
Ключевым моментом, который вам нужно сделать, является настройка делегата, настраиваемого контроллера представления и настраиваемого контроллера анимации.
вы можете использовать стороннюю библиотеку, вы можете искать их в github.com
или cocoacontrols.com
качестве навигационного ящика
В моем случае я использую этот https://github.com/CosmicMind/Material#NavigationDrawer
другие https://www.cocoacontrols.com/search?q=Drawer
https://github.com/dekatotoro/SlideMenuControllerSwift