web-dev-qa-db-ger.com

So zeigen Sie den View Controller in iOS mit Swift von rechts nach links an

Ich verwende presentViewController, um einen neuen Bildschirm zu präsentieren 

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

Dies stellt einen neuen Bildschirm von unten nach oben dar, aber ich möchte, dass er von rechts nach links angezeigt wird, ohne UINavigationController zu verwenden. 

Ich verwende Xib anstelle des Storyboards. Wie kann ich das tun?

55
Umair Afzal

Es spielt keine Rolle, ob Sie xib oder storyboard verwenden. Normalerweise wird der Übergang von rechts nach links verwendet, wenn Sie einen View-Controller in die UINavigiationController des Presenters verschieben.

UPDATE

Timing-Funktion hinzugefügt kCAMediaTimingFunctionEaseInEaseOut

Beispielprojekt mit Swift 4 Implementierung zu GitHub hinzugefügt


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)

Anscheinend ist der Parameter animated in der Methode presentViewController in diesem Fall eines benutzerdefinierten Übergangs nicht wirklich wichtig. Es kann einen beliebigen Wert haben, entweder true oder false.

119
mrvincenzo

Vollständiger Code für Gegenwart/Entlassung, 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)
    }
}

Sie können auch benutzerdefinierte Segmente verwenden.

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)
    }
    )
}
}
12
Photon Point

Lesen Sie alle Antworten und können keine korrekte Lösung sehen. Der richtige Weg ist, benutzerdefinierte UIViewControllerAnimatedTransitioning für präsentierte VC -Delegate vorzunehmen. 

Es wird also davon ausgegangen, dass Sie mehr Schritte ausführen, das Ergebnis ist jedoch anpassbarer und hat keine Nebeneffekte, z.

Nehmen Sie an, Sie haben ViewController, und es gibt eine Methode zum Präsentieren

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 und dismissTransition werden zur Animation Ihrer View-Controller verwendet. Sie übernehmen also Ihren ViewController in UIViewControllerTransitioningDelegate:

extension ViewController: UIViewControllerTransitioningDelegate {
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return presentTransition
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return dismissTransition
    }
}

Der letzte Schritt ist also die Erstellung eines benutzerdefinierten Übergangs:

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 dieser Codeansicht wird der Controller über den aktuellen Kontext dargestellt. Hier können Sie Anpassungen vornehmen. Sie können auch sehen, dass benutzerdefinierte UIPresentationController nützlich ist (übergeben Sie mit UIViewControllerTransitioningDelegate).

11
HotJard

Versuche dies,

    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)

Hier ist vc viewcontroller, in Ihrem Fall dashboardWorkout.

6
Lion

Wenn Sie die CATransition-Methode "Quick Fix" verwenden möchten ....

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
}

und dann ...

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 dies ist leider nicht wirklich korrekt :(

CATransition ist für diese Arbeit nicht wirklich geeignet.

Beachten Sie, dass Sie das ärgerliche cross-Fade zu schwarz bekommen, was den Effekt leider ruiniert.


Viele Entwickler (wie ich) mögen NavigationController wirklich nicht. Oft ist es flexibler, Ad-hoc-Präsentationen zu erstellen, insbesondere für ungewöhnliche und komplexe Apps. Es ist jedoch nicht schwierig, einen Nav-Controller "hinzuzufügen".

  1. gehen Sie einfach im Storyboard zum Eintrag VC und klicken Sie auf "embed -> in nav controller". Wirklich das ist es. Oder,

  2. in didFinishLaunchingWithOptions ist es einfach, Ihren Nav-Controller zu bauen, wenn Sie möchten

  3. sie brauchen die Variable wirklich nicht überall zu behalten, da .navigationController immer als Eigenschaft verfügbar ist - einfach.

Wenn Sie einmal einen navigationController haben, ist es einfach, Übergänge zwischen Bildschirmen durchzuführen.

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

und Sie können pop.

Das gibt Ihnen jedoch nur den Standard-Apple-Effekt "Dual Push" ...

(Die alte rutscht mit niedrigerer Geschwindigkeit ab, während die neue weiter gleitet.)

Im Allgemeinen und überraschenderweise müssen Sie sich normalerweise anstrengen, um einen vollständigen benutzerdefinierten Übergang durchzuführen.

Selbst wenn Sie nur den einfachsten, häufigsten Übergangs- oder Ausstiegsübergang wünschen, müssen Sie einen vollständigen benutzerdefinierten Übergang durchführen.

Zum Glück gibt es auf dieser QA einige Code-Codes für das Kopieren und Einfügen ... https://stackoverflow.com/a/48081504/294884 .

4
Fattie

Versuche dies.

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)
1
Ashwin Felix

präsentieren Sie den View-Controller in iOS mit Swift von rechts nach links

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]

0
FURKAN VIJAPURA

importieren Sie UIKit und erstellen Sie eine Erweiterung für 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)
}}

nach einem einfachen Anruf:

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

von links nach rechts:

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

sie können die Dauer mit Ihrer bevorzugten Dauer ändern ...

0
Fabio
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)
0
Chilli