Как представить контроллер вида справа налево в iOS с помощью Swift


я использую presentViewController, чтобы представить новый экран

let dashboardWorkout = DashboardWorkoutViewController()
presentViewController(dashboardWorkout, animated: true, completion: nil)

это представляет новый экран снизу вверх, но я хочу, чтобы он был представлен справа налево без использования UINavigationController.

Я использую Xib вместо раскадровки, так как я могу это сделать ?

10 51

10 ответов:

это не имеет значения, если это xib или storyboard что вы используете. Как правило, справа налево переход используется, когда вы нажимаете на контроллере вид на ведущей в UINavigiationController.

обновление

добавлена функция времени kCAMediaTimingFunctionEaseInEaseOut

пример проекта С Swift 4 реализация добавлена в GitHub


Swift 3 & 4

let transition = CATransition()
transition.duration = 0.5
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
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)

кажется на presentViewController метод на самом деле не имеет значения в этом случае пользовательского перехода. Он может иметь любое значение, либо true или false.

полный код для present / dismiss, 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)
    }
}

вы также можете использовать пользовательские темы.

Swift 3

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: UIViewAnimationOptions.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. Часто, он более гибок к просто присутствует в специальной манере, как вы идете, особенно для необычных и сложных приложений. Тем не менее, это не трудно "добавить" навигационный контроллер.

  1. просто на раскадровке, перейдите к записи VC и нажмите кнопку "embed -> in nav controller". Вот именно. Или,

  2. in didFinishLaunchingWithOptions это легко построить свой навигационный контроллер, если вы предпочитаете

  3. вам действительно даже не нужно держать переменную в любом месте, как .navigationController is всегда в наличии, как свойство-легко.

действительно, как только у вас есть navigationController, это тривиально делать переходы между экранами,

    let nextScreen = instantiateViewController etc as! NextScreen
    navigationController?
        .pushViewController(nextScreen, animated: true)

и pop.

что однако только дает вам стандартное яблоко" двойной толчок " эффект...

(старый соскальзывает на более низкой скорости, как новый скользит дальше.)

вообще и удивительно, вы обычно должны приложить усилия, чтобы сделать полный заказ переход.

даже если вы просто хотите самый простой, наиболее распространенный переход перемещения/перемещения, вам нужно сделать полный пользовательский переход.

к счастью, для этого есть некоторые вырезать и вставить шаблонный код на ОК... https://stackoverflow.com/a/48081504/294884 . С Новым 2018 годом!

прочитайте все ответы и не можете увидеть правильное решение. Правильный способ сделать это-сделать пользовательский 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)
        })
    }
}

в этом контроллере представления кода представлен в текущем контексте, вы можете сделать свои настройки с этой точки. Также вы можете увидеть custom UIPresentationController также полезно (передать с помощью UIViewControllerTransitioningDelegate)

попробуйте это.

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)

У меня есть лучшее решение, которое сработало для меня, если вы хотите сохранить классическую анимацию Apple, не видя этого "черного" перехода, который вы видите с помощью CATransition(). Просто используйте метод popToViewController.

вы можете искать viewController вам нужно в

self.navigationController.viewControllers // Array of VC that contains all VC of current stack

вы можете искать viewController вам нужно, ища его restorationIdentifier.

будьте осторожны: например, если вы перемещаетесь через 3 контроллера вида, и когда прибудете к последнему вы хотите поп первым. В этом случае вы потеряете ссылку на эффективный контроллер второго вида, потому что popToViewController перезаписал его. Кстати, есть решение: вы можете легко сохранить перед popToViewcontroller, VC вам понадобится позже. Это сработало для меня очень хорошо.

присутствует контроллер вида справа налево в 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"
}

Refrence By: [https://developer.apple.com/documentation/quartzcore/catransition][1]

это сработало для меня:

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