Как представить контроллер представления слева направо в iOS?

При добавлении нового контроллера в стек навигации:

self.navigationController!.pushViewController(PushedViewController(), animated: true)

он появляется справа:

Как представить контроллер представления слева направо в iOS?

Как изменить направление анимации, чтобы она отображалась слева?

Хотите подтолкнуть или представить ViewController?

Sanjay Shah 07.08.2018 13:40

Это очень сильно противоречит руководящим принципам Apple по дизайну и, вероятно, будет сбивать с толку ваших пользователей.

ZGski 08.08.2018 15:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
17
2
14 815
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Вам нужно будет написать свою собственную процедуру перехода, чтобы удовлетворить ваши потребности.

DOCS от Apple:

https://developer.apple.com/documentation/uikit/uiviewcontrollercontexttransitioning

Статья:

https://medium.com/@ludvigeriksson/custom-interactive-uinavigationcontroller-transition-animations-in-swift-4-a4b5e0cefb1e

вы можете использовать стороннюю библиотеку, вы можете искать их в github.com или cocoacontrols.com в качестве навигационного ящика

В моем случае я использую это https://github.com/CosmicMind/Material#NavigationDrawer

другие https://www.cocoacontrols.com/search?q=Drawer

https://github.com/dekatotoro/SlideMenuControllerSwift

https://github.com/jonkykong/SideMenu

Ответ принят как подходящий

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)
    }

Это помогло. Я владел тобой.

coders 24.03.2019 11:19

Я попытался проверить это на игровой площадке и получил «Не удалось проанализировать выражение, неизвестная ошибка».

Le Mot Juiced 14.06.2020 16:45

Здорово! Спасибо. Но у меня есть вопрос. Как убрать тень в этой анимации? Если я использую функцию pushViewController для iOS по умолчанию - новое представление появляется без тени под ним. Но если я использую ваш код, я вижу тень.

VyacheslavBakinkskiy 13.10.2020 13:17
let obj = self.storyboard?.instantiateViewController(withIdentifier: "ViewController")as! ViewController
            
let transition:CATransition = CATransition()
transition.duration = 0.3
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
transition.type = .push
transition.subtype = .fromLeft
self.navigationController?.view.layer.add(transition, forKey: kCATransition)

self.navigationController?.pushViewController(obj, animated: true)

Whene you use popToViewController that Time

 transition.subtype = kCATransitionFromRight

спас мой день, спасибо

Mina 06.05.2019 16:37

Хорошо, вот вам оперативное решение. Добавьте файл с именем 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)

Если вы хотите узнать, как выполнять пользовательские переходы (т.е.представлять справа налево), тогда это - довольно хорошее руководство для их настройки.

Ключевыми вещами, которые вам нужно сделать, является настройка делегата перехода, настраиваемого контроллера представления и настраиваемого контроллера анимации.

Я использовал Герой как решение.

import Hero

Затем в том месте, где вы собираетесь показать новый UIViewController, включите анимацию по умолчанию:

Hero.shared.defaultAnimation = HeroDefaultAnimationType.cover(direction: .right)

Также укажите, что ваш UINavigationController будет использовать библиотеку Hero:

self.navigationController?.hero.isEnabled = true

После этого вы получите ожидаемый результат, даже если используете стандартную функцию pushViewController:

self.navigationController?.pushViewController(vc, animated: true)

Другие вопросы по теме