1. ホーム
  2. アイオス

[解決済み】ナビゲーションベースのアプリでPushとPopのアニメーションを変更する方法

2022-04-03 10:12:50

質問

ナビゲーションベースのアプリケーションを使用していますが、プッシュとポップのアニメーションを変更したいです。どうすればよいでしょうか?

2018年を編集する

この質問には多くの回答があり、かなり時間が経過していますが、現在最も適切と思われる回答を選び直しました。もし、そうでないと思う方がいらっしゃいましたら、コメントで教えてください。

どのように解決するのですか?

<ブロッククオート

ナビゲーションベースのアプリでPushとPopのアニメーションを変更するには...

前置き

あなたがiOSの開発を始めたばかりだとします。Appleは2つのトランジションを提供していて、簡単に使うことができます。クロスフェード」と「フリップ」です。

しかし、もちろん、クロスフェードもフリップも使い物になりません。決して使われることはありません。なぜAppleがこの2つの無駄なトランジションを提供したのか、誰も知らないのです!

だから

を行いたいとします。 普通の、一般的な、トランジション 例えば、"slide" のようなものです。その場合 膨大な作業をしなければならないのです。 .

その作業については、この記事で説明しています。

繰り返しになりますが

意外なことに、iOSでは 最もシンプルで、最も一般的で、日常的なトランジション (普通のスライドなど) を行うには すべての作業 を実装することで フルカスタムトランジション .

その方法を紹介します.

1. あなたは、カスタム UIViewControllerAnimatedTransitioning

  1. のような自前のboolが必要です。 popStyle . (ポップオンなのか、ポップオフなのか).

  2. を含める必要があります。 transitionDuration (些細なことですが)とメインコールがあります。 animateTransition

  3. 実際、あなたは しなければならない 内部用に2つの異なるルーチンを書きます。 animateTransition . ひとつはプッシュ用、もうひとつはポップ用です。 おそらくこれらの名前は animatePushanimatePop . 内部 animateTransition で分岐するだけです。 popStyle という2つのルーチンに

  4. 以下の例では、単純なムーブオーバー/ムーブオフを行っています。

  5. あなたの animatePushanimatePop ルーチンを使用します。あなたは 必須 は、"from view" と "to view" を取得します。(その方法は、コード例で紹介しています)。

  6. そしてあなたは しなければならない addSubview を新しいビューに追加しました。

  7. そして、あなたは しなければならない コール completeTransition アニメの最後に

だから......。

  class SimpleOver: NSObject, UIViewControllerAnimatedTransitioning {
        
        var popStyle: Bool = false
        
        func transitionDuration(
            using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.20
        }
        
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            
            if popStyle {
                
                animatePop(using: transitionContext)
                return
            }
            
            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
            
            let f = transitionContext.finalFrame(for: tz)
            
            let fOff = f.offsetBy(dx: f.width, dy: 55)
            tz.view.frame = fOff
            
            transitionContext.containerView.insertSubview(tz.view, aboveSubview: fz.view)
            
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    tz.view.frame = f
            }, completion: {_ in 
                    transitionContext.completeTransition(true)
            })
        }
        
        func animatePop(using transitionContext: UIViewControllerContextTransitioning) {
            
            let fz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)!
            let tz = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
            
            let f = transitionContext.initialFrame(for: fz)
            let fOffPop = f.offsetBy(dx: f.width, dy: 55)
            
            transitionContext.containerView.insertSubview(tz.view, belowSubview: fz.view)
            
            UIView.animate(
                withDuration: transitionDuration(using: transitionContext),
                animations: {
                    fz.view.frame = fOffPop
            }, completion: {_ in 
                    transitionContext.completeTransition(true)
            })
        }
    }

そして ...

2. ビューコントローラーで使用します。

注:不思議なことに、あなたは を実行するだけです。 をビューコントローラに追加します。 (その下にあるものです。)

にポチッとするやつで トップ を行う。 何もない . 簡単だ。

では、あなたのクラスは...

class SomeScreen: UIViewController {
}

は...

class FrontScreen: UIViewController,
        UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {
    
    let simpleOver = SimpleOver()
    

    override func viewDidLoad() {
        
        super.viewDidLoad()
        navigationController?.delegate = self
    }

    func navigationController(
        _ navigationController: UINavigationController,
        animationControllerFor operation: UINavigationControllerOperation,
        from fromVC: UIViewController,
        to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        
        simpleOver.popStyle = (operation == .pop)
        return simpleOver
    }
}

以上です。

通常と全く同じようにプッシュ&ポップを行い、変化なし。押すには ...

let n = UIStoryboard(name: "nextScreenStoryboardName", bundle: nil)
          .instantiateViewController(withIdentifier: "nextScreenStoryboardID")
          as! NextScreen
navigationController?.pushViewController(n, animated: true)

をクリックし、次の画面でそれを実行することができます。

class NextScreen: TotallyOrdinaryUIViewController {
    
    @IBAction func userClickedBackOrDismissOrSomethingLikeThat() {
        
        navigationController?.popViewController(animated: true)
    }
}

ふぅ。


3. AnimatedTransitioningをオーバーライドする方法については、このページの他の回答もお楽しみください !

AlanZeinoと@eliasの回答までスクロールしてください。 AnimatedTransitioning 最近のiOSアプリでは