繁体   English   中英

我的子视图没有使用视图控制器制作动画

[英]My subviews doesn't animate with the view controller

我有一个简单的示例项目,其中我正在播放一些视图控制器自定义动画,以集成到更大的项目中,但我发现它们存在一些问题。

我有 2 个简单的视图控制器,第一个带有按钮来呈现第二个,带有自定义动画; 第二个有一些标签和一个关闭按钮,可以将视图控制器设置为“脱离场景”

当我呈现视图控制器时,在单击呈现按钮后,呈现的视图控制器的子视图在视图控制器动画之前出现在屏幕上,但是当我关闭 VC 时,所有子视图都与解除视图控制器。

在我的视图控制器 2(呈现)上,我有默认自动布局的视图(重置为建议的约束)

我找不到为什么子视图没有按预期在视图控制器内部设置动画的理由。

下面是一个 gif 显示正在发生的事情,以及源代码:

动图

代码:视图控制器 1(呈现 VC)

import UIKit

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

    // REMARK: UIViewControllerTransitioningDelegate
    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)
    }

}

代码:视图控制器 2(呈现 VC)

import UIKit

class ViewController2: UIViewController {

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

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

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

}

代码:CustomPresentationController

import UIKit
import Foundation

class CustomPresentationController: 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:动画师类

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

}

好的,我会尽力帮助你。 首先,它不起作用的原因是自动布局已定位您的视图,但基本上您的框架大小为零。 为了向您展示这一点,请转到有问题的控制器并让它剪辑其子视图,并且它们不会在过渡期间出现。 现在我可能不会更改框架以将其移入,因为您只想将其滑入并且您可能可以摆脱一些代码。 这就是我的样子。

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)

        }

    }

}

这就是你所需要的。 干杯。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM