如何使用 Swift 在 iOS 中从右到左呈现视图控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37722323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:18:21  来源:igfitidea点击:

How to present view controller from right to left in iOS using Swift

iosswiftswift2segue

提问by Umair Afzal

I am using presentViewController to present new screen

我正在使用 presentViewController 来呈现新屏幕

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

This presents new screen from bottom to top but I want it to presented from right to left without using UINavigationController.

这从下到上显示了新屏幕,但我希望它从右到左显示而不使用UINavigationController.

I am using Xib instead of storyboard so how can I do that ?

我正在使用 Xib 而不是故事板,所以我该怎么做?

回答by mrvincenzo

It doesn't matter if it is xibor storyboardthat you are using. Normally, the right to left transition is used when you push a view controller into presentor's UINavigiationController.

它是xibstoryboard您正在使用都无关紧要。通常,当您将视图控制器推入演示者的UINavigiationController.

UPDATE

更新

Added timing function kCAMediaTimingFunctionEaseInEaseOut

增加计时功能 kCAMediaTimingFunctionEaseInEaseOut

Sample projectwith Swift 4implementation added to GitHub

示例项目斯威夫特4实现加入GitHub上


Swift 3 & 4.2


斯威夫特 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


斯威夫特 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)

Seems like the animatedparameter in the presentViewControllermethod doesn't really matter in this case of custom transition. It can be of any value, either trueor false.

在这种自定义转换的情况下,似乎方法中的animated参数presentViewController并不重要。它可以是任何值,或者truefalse

回答by Дмитрий Боровиков

Complete code for present/dismiss, Swift 3

显示/关闭的完整代码,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)
    }
}

回答by HotJard

Read up all answers and can't see correct solution. The right way do to so is to make custom UIViewControllerAnimatedTransitioning for presented VC delegate.

阅读所有答案,但看不到正确的解决方案。正确的做法是为呈现的 VC 委托制作自定义 UIViewControllerAnimatedTransitioning。

So it assumes to make more steps, but the result is more customizable and haven't some side effects, like moving from view together with presented view.

所以它假设执行更多步骤,但结果更可定制并且没有一些副作用,例如从视图与呈现的视图一起移动。

So, assume you have some ViewController, and there is a method for presenting

所以,假设你有一些 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
    })
}

presentTransitionand dismissTransitionis used for animating your view controllers. So you adopt your ViewController to UIViewControllerTransitioningDelegate:

presentTransitiondismissTransition用于为您的视图控制器设置动画。所以你采用你的 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
    }
}

So the last step is to create your custom transition:

所以最后一步是创建您的自定义过渡:

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

In that code view controller is presented over current context, you can make your customizations from that point. Also you may see custom UIPresentationControlleris useful as well (pass in using UIViewControllerTransitioningDelegate)

在该代码视图控制器显示在当前上下文中,您可以从该点进行自定义。您也可能会看到 customUIPresentationController也很有用(传入 using UIViewControllerTransitioningDelegate

回答by Photon Point

You can also use custom segue.

您还可以使用自定义转场。

Swift 5

斯威夫特 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)
        })
    }
}

回答by Ketan Parmar

Try this,

尝试这个,

    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)

Here vcis viewcontroller, dashboardWorkoutin your case.

在您的情况下vc,这是视图控制器dashboardWorkout

回答by Fattie

If you do want to use the "quick fix" CATransition method....

如果您确实想使用“快速修复”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
}

and then ...

进而 ...

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
}

All of this is unfortunately not really correct :(

不幸的是,所有这些都不是真的正确:(

CATransitionis not really made for doing this job.

CATransition并不是真正适合做这项工作。

Note you will get the annoying cross fade to blackwhich unfortunately ruins the effect.

请注意,您将获得令人讨厌的交叉淡入淡出到黑色,不幸的是,这会破坏效果。



Many devs (like me) really don't like using NavigationController. Often, it is more flexible to just present in an ad-hoc manner as you go, particularly for unusual and complex apps. However, it's not difficult to "add" a nav controller.

许多开发人员(如我)真的不喜欢使用NavigationController. 通常,在进行时以临时方式呈现更灵活,特别是对于不寻常和复杂的应用程序。然而,“添加”一个导航控制器并不难。

  1. simply on storyboard, go to the entry VC and click "embed -> in nav controller". Really that's it. Or,

  2. in didFinishLaunchingWithOptionsit's easy to build your nav controller if you prefer

  3. you really don't even need to keep the variable anywhere, as .navigationControlleris always available as a property - easy.

  1. 只需在情节提要上,转到条目 VC 并单击“嵌入 - > 在导航控制器中”。真的就是这样。或者,

  2. didFinishLaunchingWithOptions如果您愿意,可以轻松构建导航控制器

  3. 你甚至不需要将变量保存在任何地方,因为.navigationController它总是作为属性可用 - 很容易。

Really, once you have a navigationController, it's trivial to do transitions between screens,

真的,一旦你有了一个导航控制器,在屏幕之间进行转换就很简单了,

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

and you can pop.

你可以pop

That however only gives you the standard apple "dual push" effect...

然而,这只会给你标准的苹果“双推”效果......

(The old one slides off at a lower speed, as the new one slides on.)

(旧的以较低的速度滑落,而新的则滑行。)

Generally and surprisingly, you usually have to make the effort to do a full custom transition.

通常,令人惊讶的是,您通常必须努力进行完整的自定义过渡。

Even if you just want the simplest, most common, move-over/move-off transition, you do have to do a full custom transition.

即使您只想要最简单、最常见的移动/移动过渡,您也必须进行完整的自定义过渡。

Fortunately, to do that there's some cut and paste boilerplate code on this QA... https://stackoverflow.com/a/48081504/294884. Happy new year 2018!

幸运的是,要做到这一点,这个 QA 中有一些剪切和粘贴样板代码...... https://stackoverflow.com/a/48081504/294884。2018 年新年快乐!

回答by Fabio

import UIKit and create one extension for UIViewController:

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

after simlpy call:

简单调用后:

let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromRight)

from left to right:

从左到右:

let vC = YourViewController()
transitionVc(vc: vC, duration: 0.5, type: .fromleft)

you can change the duration with your preferred duration...

您可以使用您喜欢的持续时间更改持续时间...

回答by Ashwin Felix

Try this.

尝试这个。

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)

回答by FURKAN VIJAPURA

present view controller from right to left in iOS using Swift

使用 Swift 在 iOS 中从右到左呈现视图控制器

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]

参考:[ https://developer.apple.com/documentation/quartzcore/catransition][1]

回答by Chilli

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)