2017-03-17 6 views
0

私は、より大きなプロジェクトに統合するために、いくつかのビューコントローラのカスタムアニメーションを再生しているシンプルなサンプルプロジェクトを持っていますが、私のサブビューはビューコントローラでアニメートしません

私は2つのシンプルなビューコントローラを持っています。最初のものは2番目のものを表示し、カスタムアニメーションは2番目のものです。 2番目にはいくつかのラベルと、シーンのビューコントローラをアニメートする「解除」ボタンがあります

現在のボタンをクリックすると、表示されたビューコントローラのサブビュー、ビューコントローラがアニメーション化される前に画面に表示されますが、VCを終了すると、すべてのサブビューは切断されたビューコントローラと一緒になります。私は内部の私は、サブビューがでアニメーション化しない理由を正当化を見つけることができません

(提案制約にリセット)デフォルトの自動レイアウトでビューをした私のビューコントローラ2(提示)で

私が予期したようにビューコントローラ。

以下

何が起こっているかを示すGIFを移行し、ソース・コード:

GIF

CODE:ビューコントローラ1(提示VC)

輸入のUIKit

クラスのViewController:のUIViewController 、UIViewControllerTransitioningDelegate {

var animator = Animator() 


override func viewDidLoad() { 
    super.viewDidLoad() 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
    // Dispose of any resources that can be recreated. 
} 


@IBAction func presentButton(_ sender: Any) { 
    let storyboard = UIStoryboard(name: "Main", bundle: nil); 
    let vc = storyboard.instantiateViewController(withIdentifier: "vc2") as! ViewController2 

    vc.transitioningDelegate = self 
    vc.modalPresentationStyle = .custom // chama as funções à parte 

    present(vc, animated: true, completion: nil) 
} 




func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
    animator.transitioningMode = .Present // sabe que está em presenting mode 
    return animator 
} 

func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
    animator.transitioningMode = .Dismiss // Sabe que está em dismissing mode 
    return animator 
} 

func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { 
    return CustomPresentationController(presentedViewController: presented, presenting: presenting) 
} 




} 

CODE:ビューコントローラ2(提示VC)

クラスViewController2

インポートのUIKit:のUIViewController {

override func viewDidLoad() { 
    super.viewDidLoad() 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
} 



@IBAction func dismissButton(_ sender: Any) { 
    dismiss(animated: true, completion: nil) 
} 

} 

CODE:CustomPresentationController

import UIKit 

インポート財団

クラスクスtomPresentationController:UIPresentationController {

override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController!) { 
    super.init(presentedViewController: presentedViewController, presenting: presentingViewController) 
} 


override var frameOfPresentedViewInContainerView: CGRect { 

    // arranca a 0 
    var presentedViewFrame = CGRect.zero 

    // Calcula os bounds do container 
    let containerBounds = self.containerView?.bounds 

    // Recalcula o size 
    presentedViewFrame.size = CGSize(width: (containerBounds?.size.width)! , height: ((containerBounds?.size.height)! * 0.90)) 

    presentedViewFrame.origin.x = 0 
    presentedViewFrame.origin.y = (containerBounds?.size.height)! * 0.1 

    return presentedViewFrame 
} 


} 

CODE:アニメータークラス

輸入財団 輸入のUIKit

クラスのアニメーター:NSObjectの、UIViewControllerAnimatedTransitioning {

enum Status { 
    case Present 
    case Dismiss 
} 
var transitioningMode: Status = .Present 
var presentDuration = 1.0 
var dismissDuration = 0.3 


// Tempo da animação 
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 
    if (transitioningMode == .Present) { 
     return presentDuration 
    } else { 
     return dismissDuration 
    } 
} 



func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 

    // Get the set of relevant objects. 
    let containerView = transitionContext.containerView 

    guard 
     let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), 
     let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) 
     else { 
      print("Returning animateTransition VC") 
      return 
    } 

    let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) 
    let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from) 



    // Set up some variables for the animation. 
    let containerFrame:  CGRect = containerView.frame 
    var toViewStartFrame: CGRect = transitionContext.initialFrame(for: toVC) 
    let toViewFinalFrame: CGRect = transitionContext.finalFrame(for: toVC) 
    var fromViewFinalFrame: CGRect = transitionContext.finalFrame(for: fromVC) 

    // Set up animation parameters. 
    if (transitioningMode == .Present) { 
     // Modify the frame of the presented view so that it starts 
     // offscreen at the lower-right corner of the container. 
     toViewStartFrame.origin.x = 0//containerFrame.size.width 
     toViewStartFrame.origin.y = containerFrame.size.height * 0.1 


    } else { 
     // Modify the frame of the dismissed view so it ends in 
     // the lower-right corner of the container view. 
     fromViewFinalFrame = CGRect(x: containerFrame.size.width, 
            y: containerFrame.size.height, 
            width: (toVC.view.frame.size.width), 
            height: (toVC.view.frame.size.height)) 



    } 

    if (transitioningMode == .Present) { 
     // Always add the "to" view to the container. 
     // And it doesn't hurt to set its start frame. 
     containerView.addSubview(toView!) 
     toView?.frame = toViewStartFrame 
    } 

    // Animate using the animator's own duration value. 
    UIView.animate(withDuration: presentDuration, animations: { 

     if (self.transitioningMode == .Present) { 
      // Move the presented view into position. 
      toView?.frame = toViewFinalFrame 
     } 
     else { 
      // Move the dismissed view offscreen. 
      fromView?.frame = fromViewFinalFrame 
     } 
    }) { (finished) in 
     let success = !(transitionContext.transitionWasCancelled) 
     // After a failed presentation or successful dismissal, remove the view. 
     if ((self.transitioningMode == .Present && !success) || (self.transitioningMode == .Dismiss && success)) { 
      toView?.removeFromSuperview() 
     } 

     // Notify UIKit that the transition has finished 
     transitionContext.completeTransition(success) 

    } 

} 



} 
+0

青の表示は、表示されているView Controllerの一番下にあるはずですか?私は問題を知っていますが、コードを表示しようとすると、あなたのユースケースに合うようにしたいと思います。ナビゲーションバーや何か – agibson007

+0

はありますか?これは現在のコンテキスト上ですか? – agibson007

+0

アニメーション効果(どこから来てどこで終わるのか、本当に重要ではない、後で変更します) –

答えて

1

さてさて、私は刺しを取るつもりですあなたを助けて最初に、なぜそれが動作していない理由は、あなたの意見を位置付けているが、基本的にサイズゼロのフレームを持っているということです。あなたにこれを示すために、問題のコントローラーに行き、そのサブビューをクリップさせて、それらはトランジション中に表示されません。今では、フレームをスライドさせたいのでフレームを移動しないでください。おそらくコードを取り除くことができます。ここは私のために見えるものです。

import UIKit 

class ViewController: UIViewController,UIViewControllerTransitioningDelegate { 

    var animator = Animator() 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    @IBAction func presentModally(_ sender: Any) { 
     self.performSegue(withIdentifier: "modal", sender: nil) 
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if segue.identifier == "modal"{ 
      let dvc = segue.destination 
      dvc.transitioningDelegate = self 
      dvc.modalPresentationStyle = .overCurrentContext 
     } 
    } 

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     animator.transitioningMode = .Present // sabe que está em presenting mode 
     return animator 
    } 

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 
     animator.transitioningMode = .Dismiss // Sabe que está em dismissing mode 
     return animator 
    } 

} 

カスタムプレゼンテーションコントローラを削除します。私は正直なところ、それが必要ではないと思う。

アニメーターが完成しました。

import UIKit 

class Animator: NSObject,UIViewControllerAnimatedTransitioning { 
    enum Status { 
     case Present 
     case Dismiss 
    } 
    var transitioningMode: Status = .Present 
    var presentDuration = 1.0 
    var dismissDuration = 0.3 


    // Tempo da animação 
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 
     if (transitioningMode == .Present) { 
      return presentDuration 
     } else { 
      return dismissDuration 
     } 
    } 


    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 

     // Get the set of relevant objects. 
     let containerView = transitionContext.containerView 

     guard 
      let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), 
      let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) 
      else { 
       print("Returning animateTransition VC") 
       return 
     } 

     let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) 
     let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from) 

     // Set up some variables for the animation. 
     let containerFrame:  CGRect = containerView.frame 
     let toViewFinalFrame: CGRect = transitionContext.finalFrame(for: toVC) 
     var fromViewFinalFrame: CGRect = transitionContext.finalFrame(for: fromVC) 

     // Set up animation parameters. 
     if (transitioningMode == .Present) { 
      let anchor = toViewFinalFrame.origin 
      toView?.layer.anchorPoint = anchor 
      toView?.layer.position = anchor 
      toView?.transform = CGAffineTransform(scaleX: 0, y: 1) 
      //another posibility 
      //toView?.transform = CGAffineTransform(translationX: -containerView.bounds.width, y: -containerView.bounds.height) 
     } else { 
      // Modify the frame of the dismissed view so it ends in 
      // the lower-right corner of the container view. 
      fromViewFinalFrame = CGRect(x: containerFrame.size.width, 
             y: containerFrame.size.height, 
             width: (toVC.view.frame.size.width), 
             height: (toVC.view.frame.size.height)) 
     } 

     if (transitioningMode == .Present) { 
      // Always add the "to" view to the container. 
      // And it doesn't hurt to set its start frame. 
      containerView.addSubview(toView!) 
      // toView?.frame = toViewStartFrame 
     } 

     // Animate using the animator's own duration value. 
     UIView.animate(withDuration: presentDuration, animations: { 

      if (self.transitioningMode == .Present) { 
       // Move the presented view into position. 
       toView?.transform = .identity 
      } 
      else { 
       // Move the dismissed view offscreen. 
       fromView?.frame = fromViewFinalFrame 
      } 
     }) { (finished) in 
      let success = !(transitionContext.transitionWasCancelled) 
      // After a failed presentation or successful dismissal, remove the view. 
      if ((self.transitioningMode == .Present && !success) || (self.transitioningMode == .Dismiss && success)) { 
       toView?.removeFromSuperview() 
      } 

      // Notify UIKit that the transition has finished 
      transitionContext.completeTransition(success) 

     } 

    } 

} 

これだけです。乾杯。

+0

私は未来であればカスタムプレゼンテーションクラスが必要だと思った私はビューコントローラのサイズを変更したいと思っていました。私はあなたが書いたことを試してみるでしょう、そして、私はすぐにそれをフィードバックします。助けてくれてありがとう:) –

+0

カスタムプレゼンテーションコントローラを保持することができますが、私はあなたがフレームをしたいと正確なサイズを返し、翻訳またはスケールを使用して場所に移動します。ちょうど私の2セント。私がアニメーションを行い、実際にフレームを変更しようとしているとき、私は一般的にスナップショットを撮り、オリジナルを隠して最後にスナップショットを取り除き、削除します。しかし、私はビューまたはサブビューのスナップショットのみをアニメートします。そうすれば、私は実際の視界のフレームを決して操作することはありません。これがまた役立つことを願っています。 – agibson007

+0

ニースのヒント。あなたはmail.appのiOS 10.3で新しいアニメーションを見たことがありますか?新しい電子メールを作成しているとき、View Controllerは下部から来ていますが、上部には表示されません。サイズの90%のようなものです。背景ビューコントローラは少しスケールを変え、両方見ることができます。それは私がここで作成しようとしているものです;) –

関連する問題