web-dev-qa-db-ja.com

iOSセグエ-左から右-

セグエに関する他の投稿を読みましたが、私の質問を解決できるものはありません。

簡単に言えば、私のViewControllersは本のように注文されます。後方へのトランジション(例:ページ9から8)を常に左から右に表示(スライド)したい。順方向遷移(9〜10ページ)を右から左に表示したい。

はい、ページごとにページングする場合、nav-controllerの戻るボタン(左上)はこのように表示されます。ただし、インデックスからジャンプすると、navコントローラの戻る機能によりインデックスに戻ります。

私の目的は、ユーザーがインデックスから(たとえば)ページ9にジャンプしてから右にスワイプすると、ページを右にフリックしてページ8を表示することです。左にフリックすると、再び9ページ目になります。

すべてのViewControllersは、デフォルトでは、右から左にスライドして表示されます。

例:インデックスを使用して第4章に移動し、右にスワイプしてスタックからビューをポップすると、本のように考えると、インデックスに戻ります。しかし、394ページの第4章にいて右にスワイプした場合、インデックスに戻りたくありません! 393ページの第3章の最後のページに移動します!そのため、ナビゲーションスタックは役に立たない。

終了例

詳細:1.ボタンタップの新しいXcode「表示」を使用して、ViewControllerを切り替えます。

  1. 左上の「戻る」ボタンの機能に、Navigation Controllerを使用しています。これはnavスタックを使用し、正常に機能します。

  2. ただし、下部に独自のカスタムナビゲーションバー(戻るボタン、ホームボタン、インデックスボタン、進むボタン)とジェスチャーがあります。これらは、本のような機能を持ちたいものです。

  3. Swiftでのコーディング。

  4. Xcode 6.3での作業

アニメーションコードがあることを読みました。私は、使用できるプログラム遷移を詳細に読んだことがあります。左から提示したいセグエを選択して、簡単にアニメーションを反転させる簡単な方法はないのはおかしいようです。

ありがとう!

試行ログ:

I tried DCDC's code:
    UIView.transitionWithView(self.window!, duration: 0.5, options:.TransitionFlipFromLeft, animations: { () -> Void in
            self.window!.rootViewController = mainVC
            }, completion:nil)

このエラーは、バックスワイプのためにDCDCのコードをIBActionに挿入すると返されます

This error is returned when I insert DCDC's code into an IBAction for my back-swipe

39
Dave G

これは、nav-controllerを必要とせずに効果を達成する方法です。代わりにこれを試してください:

スウィフト4:

import UIKit
class SegueFromLeft: 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: .curveEaseInOut,
                         animations: {
                                dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
                                },
                        completion: { finished in
                                src.present(dst, animated: false, completion: nil)
                                    }
                        )
    }
}

スウィフト3:

import UIKit

class SegueFromLeft: UIStoryboardSegue
{
    override func perform()
    {
        let src = self.sourceViewController
        let dst = self.destinationViewController

        src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
        dst.view.transform = CGAffineTransformMakeTranslation(-src.view.frame.size.width, 0)

        UIView.animateWithDuration(0.25,
            delay: 0.0,
            options: UIViewAnimationOptions.CurveEaseInOut,
            animations: {
                dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
            },
            completion: { finished in
                src.presentViewController(dst, animated: false, completion: nil)
            }
        )
    }
}

次に、ストーリーボードで、変更するセグエをクリックします。属性インスペクターで、タイプを「Custom」に変更し、クラスを「SegueFromLeft」に変更します

86
Michael Hudson

以下は、Swiftで左から右へのセグエを実行するために使用できるカスタムセグエクラスです。 QuartzCoreフレームワークと最小限のアニメーションが必要です。

スイフト2.2

import UIKit
import QuartzCore

class SegueFromLeft: UIStoryboardSegue {

    override func perform() {
        let src: UIViewController = self.sourceViewController
        let dst: UIViewController = self.destinationViewController
        let transition: CATransition = CATransition()
        let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.duration = 0.25
        transition.timingFunction = timeFunc
        transition.type = kCATransitionPush
        transition.subtype = kCATransitionFromLeft
        src.navigationController!.view.layer.addAnimation(transition, forKey: kCATransition)
        src.navigationController!.pushViewController(dst, animated: false)
    }

}

Swift 3.0

import UIKit
import QuartzCore

class SegueFromLeft: UIStoryboardSegue {

    override func perform() {
        let src: UIViewController = self.source
        let dst: UIViewController = self.destination
        let transition: CATransition = CATransition()
        let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        transition.duration = 0.25
        transition.timingFunction = timeFunc
        transition.type = kCATransitionPush
        transition.subtype = kCATransitionFromLeft
        src.navigationController!.view.layer.add(transition, forKey: kCATransition)
        src.navigationController!.pushViewController(dst, animated: false)
    }
}

「戻る」ボタンは、移行されたView ControllerのNavigation Barに表示されたままですが、そのView ControllerのNavigation Controllerを簡単に無効化/設定できます。

41
rambossa

Swift 3:

import UIKit

class SegueFromLeft: 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)
            }
        )
    }
}
11
Mark Barrasso

承認済み回答Swift 3に更新(2017年6月現在)

セグエからleft to right

import UIKit

class SegueFromLeft: UIStoryboardSegue {
    override func perform() {
        let src = self.source       //new enum
        let dst = self.destination  //new enum

        src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
        dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0) //Method call changed
        UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: { 
            dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
        }) { (finished) in
            src.present(dst, animated: false, completion: nil) //Method call changed
        }
    }
}

right to leftからセグエ

import UIKit

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*2, y: 0) //Double the X-Axis
        UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: { 
            dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
        }) { (finished) in
            src.present(dst, animated: false, completion: nil)
        }
    }
}
4
Annjawn

TransitionWithViewメソッドで事前宣言されたタイプの遷移を使用できます

UIView.transitionWithView(self.window!, duration: 0.5, options:.TransitionFlipFromLeft, animations: { () -> Void in
            self.window!.rootViewController = mainVC
            }, completion:nil)

.TransitionFlipFromLeftが望ましいものだと思います

タスクを完了するには、新しいView Controllerをストーリーボードにドラッグし、IDを付けて名前を付けます。これが移行の宛先になります。

次に、コードからこのView Controllerをインスタンス化します

let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let mainVC = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! UIViewController

これは、IBAction内またはViewDidLoadなどで実行できますが、おそらくIBActionの方が適しています。ストーリーボードとView Controllerの両方に正しい識別子を入力するよう注意してください。また、appDelegateインスタンスを宣言する必要があります。実装されたIBActionは次のとおりです。

@IBAction func Push(sender: UIButton) {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let mainVC = storyboard.instantiateViewControllerWithIdentifier("secondVC") as! UIViewController
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    UIView.transitionWithView(appDelegate.window!, duration: 0.5, options: .TransitionFlipFromLeft , animations: { () -> Void in
        appDelegate.window!.rootViewController = mainVC
        }, completion:nil)
}

これが期待したものでない場合は、おそらくカスタムアニメーションを作成することをお勧めします。この記事は本当に役に立ちます: http://mathewsanders.com/animated-transitions-in-Swift/

4
DCDC

デフォルトの戻るボタンのように、UINavigationControllerのスタックからView Controllerをポップしようとしているようです。

次の2つのいずれかを実行できます。最も簡単な方法は、カスタムバックボタンをpopViewControllerAnimated()を呼び出すIBActionに接続することです。

@IBAction func tappedCustomBackButton(sender: AnyObject) {
    self.navigationController?.popViewControllerAnimated(true)
}

または、2番目のView Controllerから最初のView Controllerに nwind segue を作成できます。

2
Richard Venable

右からセグエ。以下のようにセグエのperform関数をオーバーライドできます。この関数をカスタムセグエクラス内に配置し、このクラスをセグエに割り当てます。 Navigation Controllerを備えたコントローラーとNavigation Controllerを備えていないコントローラーの両方で機能します

override func perform()
{
    let src = self.sourceViewController
    print(src)
    let dst = self.destinationViewController
    print(dst)

    src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
    dst.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.height, 0)

    UIView.animateWithDuration(0.35,
                               delay: 0.0,
                               options: UIViewAnimationOptions.CurveEaseInOut,
                               animations: {
                                dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
        },
                               completion: { finished in
                                if let navController = src.navigationController {
                                    navController.pushViewController(dst, animated: false)

                                } else {
                                    src.presentViewController(dst, animated: false, completion: nil)
                                }            }
    )
}

左からセグエが必要な場合は、これを使用します

CGAffineTransformMakeTranslation(-src.view.frame.size.height, 0)
1
Ashwin Felix

私の場合、サイドバーメニューを作成していました...

新しいView Controllerと2つの税関セグエを作成しました

メニューを開くには:

import Foundation
import UIKit

class SegueFromLeft: UIStoryboardSegue {

  override func perform() {

    let src = self.source as UIViewController
    let dst = self.destination as UIViewController

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

}

}

メニューを閉じるには:

import Foundation
import UIKit

class SegueFromRight: UIStoryboardSegue {

override func perform() {

    let src = self.source as UIViewController
    let dst = self.destination as UIViewController

    src.view.superview?.insertSubview(dst.view, belowSubview: src.view)
    src.view.transform = CGAffineTransform(translationX: 0, y: 0)

    UIView.animate(withDuration: 0.25,
                               delay: 0.0,
                               options: UIViewAnimationOptions.curveEaseInOut,
                               animations: {
                                src.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width, y: 0)
    },
                               completion: { finished in
                                src.dismiss(animated: false, completion: nil)
    }
    )
}
}

お役に立てば幸いです...

1

Swift 4:

class SegueFromLeft: 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)
    })
     }
}

これを受け入れられた回答にコピーして、このコメントを削除してください。 (これは単純な更新であり、新しいものはありません。)

1
aestusLabs

やあ、私は完全なソリューションを持っているので、このコードをコピーしてSwiftに貼り付けるだけです。3。

func menu(){
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "MyAccountViewController") as! MyAccountViewController

    let transition: CATransition = CATransition()
    let timeFunc : CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
    transition.duration = 0.5
    transition.timingFunction = timeFunc
    transition.type = kCATransitionPush
    transition.subtype = kCATransitionFromLeft
    self.navigationController?.view.layer.add(transition, forKey: kCATransition)
    self.navigationController?.pushViewController(vc, animated: false)
}

注:ViewControllerの名前を「MyAccountViewController」テキストで変更します。

0
MRizwan33

アニメーションのような「戻るボタン」を作成するには、これを使用します。

class SegueRightToLeft: UIStoryboardSegue {

override func perform() {
    let src = self.source       //new enum
    let dst = self.destination  //new enum

    src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
    dst.view.transform = CGAffineTransform(translationX: -src.view.frame.size.width/2, y: 0) 
    //slice the x axis translation in half

    UIView.animate(withDuration: 0.25, delay: 0.0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
        dst.view.transform = CGAffineTransform(translationX: 0, y: 0)
    }) { (finished) in
        src.present(dst, animated: false, completion: nil)
    }
}
0
Felecia Genet