2017-03-17 94 views
0

我有一個簡單的示例項目,我正在玩一些視圖控制器自定義動畫,要集成到一個更大的項目中,但我發現它們有一些問題。我的子視圖不與視圖控制器一起動畫

我有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)

進口的UIKit

類ViewController2: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 

進口基金會

類CUS 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:Animator類

進口基金會 進口的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

藍色視圖應該低於呈現視圖控制器的頂部。我知道這個問題,但是如果我要顯示代碼,我希望它符合你的用例。有沒有一個導航欄或 – 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上的新動畫?當你創建一個新的電子郵件時,視圖控制器來自底部,但沒有達到頂部,就像90%的大小,背景視圖控制器擴展了一點,你可以看到他們兩個。這就是我想在這裏創建的;) –

相關問題