CGAffineTransform.identity 设备旋转后未正确重置变换
CGAffineTransform.identity doesn't reset transform correctly after device rotation
我正在做一个自定义转换,如果在呈现动画后,设备将旋转,然后 destinationVC 将被关闭,originVC 转换不正确(不满足屏幕)。如果没有设备旋转,则一切正常。有谁能帮帮我吗?
这是我的呈现和关闭动画代码:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: 0)
originViewController.view.transform = originViewController.view.transform.scaledBy(x: 0.95, y: 0.95)
originViewController.view.layer.cornerRadius = 8.0
}, completion: { completed in
transitionContext.completeTransition(completed)
})
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
originViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
destinationViewController.view.transform = CGAffineTransform.identity
destinationViewController.view.layer.cornerRadius = 0.0
}, completion: { completed in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
屏幕:
当前动画之前
呈现动画后
设备旋转后
关闭动画后
编辑:
当我添加 destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
以关闭动画时,一切似乎都正常,但我不知道这是否正确
在 ViewC1 中添加一个带有前导、顶部、底部、尾随约束的子视图。
工作完整代码
class ViewC1: UIViewController {
@IBAction func presentNow(_ sender: Any) {
let viewc = storyboard!.instantiateViewController(withIdentifier: "ViewC2") as! ViewC2
viewc.transitioningDelegate = viewc
viewc.modalPresentationStyle = .overCurrentContext
present(viewc, animated: true, completion: nil)
}
}
class ViewC2: UIViewController {
let pres = PresentAnimator()
let diss = DismissAnimator()
@IBAction func dissmisNow(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension ViewC2: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return pres
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return diss
}
}
class PresentAnimator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1.0
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
transitionContext.containerView.addSubview(destinationViewController.view)
destinationViewController.view.frame = transitionContext.containerView.bounds
let originView = originViewController.view.subviews.first
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: 0)
originView?.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
originView?.layer.cornerRadius = 8.0
}, completion: { completed in
transitionContext.completeTransition(completed)
})
}
}
class DismissAnimator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1.0
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
let originView = destinationViewController.view.subviews.first
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
originViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
originView?.transform = CGAffineTransform.identity
originView?.layer.cornerRadius = 0.0
}, completion: { completed in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
}
更新:
或者,如果您不想使用 view.subviews.first
,则可以覆盖 willRotate 和 didRotate
var prevTrans: CGAffineTransform?
override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
prevTrans = view.transform
view.transform = CGAffineTransform.identity
}
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
if let prevTrans = prevTrans {
view.transform = prevTrans
}
}
我正在做一个自定义转换,如果在呈现动画后,设备将旋转,然后 destinationVC 将被关闭,originVC 转换不正确(不满足屏幕)。如果没有设备旋转,则一切正常。有谁能帮帮我吗?
这是我的呈现和关闭动画代码:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: 0)
originViewController.view.transform = originViewController.view.transform.scaledBy(x: 0.95, y: 0.95)
originViewController.view.layer.cornerRadius = 8.0
}, completion: { completed in
transitionContext.completeTransition(completed)
})
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
originViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
destinationViewController.view.transform = CGAffineTransform.identity
destinationViewController.view.layer.cornerRadius = 0.0
}, completion: { completed in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
屏幕:
当前动画之前
编辑:
当我添加 destinationViewController.view.frame = transitionContext.finalFrame(for: destinationViewController)
以关闭动画时,一切似乎都正常,但我不知道这是否正确
在 ViewC1 中添加一个带有前导、顶部、底部、尾随约束的子视图。 工作完整代码
class ViewC1: UIViewController {
@IBAction func presentNow(_ sender: Any) {
let viewc = storyboard!.instantiateViewController(withIdentifier: "ViewC2") as! ViewC2
viewc.transitioningDelegate = viewc
viewc.modalPresentationStyle = .overCurrentContext
present(viewc, animated: true, completion: nil)
}
}
class ViewC2: UIViewController {
let pres = PresentAnimator()
let diss = DismissAnimator()
@IBAction func dissmisNow(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension ViewC2: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return pres
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return diss
}
}
class PresentAnimator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1.0
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
transitionContext.containerView.addSubview(destinationViewController.view)
destinationViewController.view.frame = transitionContext.containerView.bounds
let originView = originViewController.view.subviews.first
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
destinationViewController.view.transform = CGAffineTransform(translationX: 0, y: 0)
originView?.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
originView?.layer.cornerRadius = 8.0
}, completion: { completed in
transitionContext.completeTransition(completed)
})
}
}
class DismissAnimator: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1.0
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
guard let originViewController = transitionContext.viewController(forKey: .from),
let destinationViewController = transitionContext.viewController(forKey: .to) else { return }
let originView = destinationViewController.view.subviews.first
let duration = transitionDuration(using: transitionContext)
UIView.animate(withDuration: duration, animations: {
originViewController.view.transform = CGAffineTransform(translationX: 0, y: destinationViewController.view.frame.height)
originView?.transform = CGAffineTransform.identity
originView?.layer.cornerRadius = 0.0
}, completion: { completed in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
}
更新:
或者,如果您不想使用 view.subviews.first
var prevTrans: CGAffineTransform?
override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
prevTrans = view.transform
view.transform = CGAffineTransform.identity
}
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
if let prevTrans = prevTrans {
view.transform = prevTrans
}
}