我的子视图不与视图控制器一起动画
我有一个简单的示例项目,我正在玩一些视图控制器自定义动画,要集成到一个更大的项目中,但我发现它们有一些问题。我的子视图不与视图控制器一起动画
我有2个简单的视图控制器,第一个带有按钮以呈现第二个,带有自定义动画;第二个有一些标签和一个解雇按钮,动画视图控制器'场景'
当我提出视图控制器,当我点击当前按钮后,呈现的视图控制器的子视图,在视图控制器开始动画之前出现在屏幕上,但是当我解散VC时,所有子视图都与解散的视图控制器一起进行。
在我的视图控制器2(提交)我已经默认自动布局(重置建议限制)
我找不到理由,为什么子视图不动画中,里面的观点视图控制器,如我所料。
下面转到示出发生了什么的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)
}
}
}
好吧,我要带刺在帮助你。首先,它不工作的原因是自动布局具有定位视图,但基本上你有一个大小为零的框架。为了向你展示这一点,请去讨论有问题的控制器,让它剪辑它的子视图,并且在转换过程中它们不会显示出来。现在我可能不会更改框架来移动它,因为您只是想将其滑入,并且可能会删除一些代码。这是我看起来的样子。
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)
}
}
}
这就是你所需要的。干杯。
我认为这是必需的他定制的演示课,如果我是未来我想改变视图控制器的大小。我会尝试你写的内容,我会尽快给你回复。感谢您的帮助:) –
您可以保留自定义的演示文稿控制器,但我会返回您想要的帧的确切大小,并使用翻译或缩放将其移入到位。只是我2美分。当我做动画时,我实际上要改变框架,我通常会拍摄快照并隐藏原始图像并取消隐藏,并在最后删除快照。但是,我只对视图或子视图的快照进行动画处理。这样我从不真正操纵真实视图的框架。希望这也有帮助。 – agibson007
不错的提示。你有没有看过mail.app的iOS 10.3上的新动画?当你创建一个新的电子邮件时,视图控制器来自底部,但没有达到顶部,就像90%的大小,背景视图控制器扩展了一点,你可以看到他们两个。这就是我想在这里创建的;) –
蓝色视图应该低于呈现视图控制器的顶部。我知道这个问题,但是如果我要显示代码,我希望它符合你的用例。有没有一个导航栏或 – agibson007
和这是在当前的上下文? – agibson007
动画效果(它来自哪里,它结束的地方不是很重要,我稍后会改变它) –