web-dev-qa-db-ja.com

iOSでSwiftを使用してView Controllerを右から左に表示する方法

PresentViewControllerを使用して新しい画面を表示しています

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

これは新しい画面を下から上に表示しますが、UINavigationControllerを使用せずに右から左に表示したいです。

ストーリーボードの代わりにXibを使用しています。

60
Umair Afzal

使用しているのがxibstoryboardかは関係ありません。通常、View ControllerをプレゼンターのUINavigiationControllerにプッシュするときに、右から左への遷移が使用されます。

UPDATE

タイミング関数kCAMediaTimingFunctionEaseInEaseOutを追加しました

サンプルプロジェクト withSwift 4実装がGitHubに追加されました


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)

この場合、animatedメソッドのpresentViewControllerパラメーターは、カスタムトランジションの場合、実際には問題ではないようです。 trueまたはfalseのいずれかの値を指定できます。

127
mrvincenzo

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

すべての答えを読んでください、正しい解決策を見ることができません。そのための正しい方法は、提示されたVCデリゲートのカスタムUIViewControllerAnimatedTransitioningを作成することです。

したがって、より多くの手順を実行することを前提としていますが、結果はよりカスタマイズ可能であり、表示されたビューと一緒にビューから移動するなどの副作用はありません。

したがって、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は、View Controllerのアニメーション化に使用されます。したがって、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)
        })
    }
}

現在のコンテキスト上に表示されるコードビューコントローラーでは、その時点からカスタマイズを行うことができます。また、カスタムUIPresentationControllerも役立つことがあります(UIViewControllerTransitioningDelegateを使用して渡す)

17
HotJard

カスタムセグエも使用できます。

Swift

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

これを試して、

    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です。

6
Lion

「簡易修正」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の使用を本当に嫌います。多くの場合、特に変わった複雑なアプリの場合は、その場でアドホックに表示する方がより柔軟です。ただし、navコントローラーを「追加」することは難しくありません。

  1. 単にストーリーボードで、エントリVCに移動し、[埋め込み->ナビゲーションコントローラに]をクリックします。本当にそれだけです。または、

  2. didFinishLaunchingWithOptionsでは、必要に応じてnavコントローラーを簡単に作成できます

  3. .navigationControllerは常にプロパティとして利用できるため、変数をどこにでも保持する必要さえありません-簡単です。

実際、navigationControllerを作成したら、画面間の遷移を行うのは簡単です。

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

popを使用できます。

ただし、標準のApple「デュアルプッシュ」効果しか得られません...

(古いものは、新しいものがスライドするので、低速でスライドします。)

一般的に、そして驚くべきことに、通常は完全なカスタム移行を行う努力をしなければなりません。

最も単純で最も一般的な、移動/移動/オフの移行が必要な場合でも、完全なカスタム移行を行う必要があります。

幸いなことに、これを行うには、このQAに定型コードの切り取りと貼り付けがあります... https://stackoverflow.com/a/48081504/294884 。明けましておめでとうございます2018!

4
Fattie

これを試して。

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

swiftを使用して、iOSでView Controllerを右から左に表示

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

uIKitをインポートし、UIViewControllerの拡張機能を1つ作成します。

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

simlpy呼び出しの後:

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

左から右へ:

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

希望の期間で期間を変更できます...

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