我使用自定义过渡来显示全屏模式游戏视图。当用户启动游戏时,根视图控制器会缩小"进入"屏幕,而全屏游戏视图控制器从较大比例缩放到显示屏上,同时从0%不透明度转换为100%不透明度。简单!
过渡看起来很棒并且工作正常,在解雇游戏视图控制器时也正确地反转动画。
我遇到的问题是,如果在显示全屏游戏视图控制器的情况下旋转设备,则在返回根视图控制器时,布局非常麻烦。并且进一步的旋转不能解决问题,布局很棘手并且仍然很棘手。
如果我禁用自定义转换,则此问题已消失。此外,如果我保留自定义转换,但禁用在转换动画中的源和目标视图上设置CATransform3D 的调用,则问题会再次消失。
这是我的过渡代表:
class FullscreenModalTransitionManager: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
private var presenting:Bool = true
// MARK: UIViewControllerAnimatedTransitioning protocol methods
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// get reference to our fromView, toView and the container view that we should perform the transition in
let container = transitionContext.containerView()
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
let scale:CGFloat = 1.075
//let bigScale = CGAffineTransformMakeScale(scale, scale)
//let smallScale = CGAffineTransformMakeScale(1/scale,1/scale)
let bigScale = CATransform3DMakeScale(scale, scale, 1)
let smallScale = CATransform3DMakeScale(1/scale, 1/scale, 1)
let smallOpacity:CGFloat = 0.5
let presenting = self.presenting
if presenting {
// when presenting, incoming view must be on top
container.addSubview(fromView)
container.addSubview(toView)
toView.layer.transform = bigScale
toView.opaque = false
toView.alpha = 0
fromView.layer.transform = CATransform3DIdentity
fromView.opaque = false
fromView.alpha = 1
} else {
// when !presenting, outgoing view must be on top
container.addSubview(toView)
container.addSubview(fromView)
toView.layer.transform = smallScale
toView.opaque = false
toView.alpha = smallOpacity
fromView.layer.transform = CATransform3DIdentity
fromView.opaque = false
fromView.alpha = 1
}
let duration = self.transitionDuration(transitionContext)
UIView.animateWithDuration(duration,
delay: 0.0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0,
options: nil,
animations: {
if presenting {
fromView.layer.transform = smallScale
fromView.alpha = smallOpacity
} else {
fromView.layer.transform = bigScale
fromView.alpha = 0
}
},
completion: nil )
UIView.animateWithDuration(duration,
delay: duration/6,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.5,
options: nil,
animations: {
toView.layer.transform = CATransform3DIdentity
toView.alpha = 1
},
completion: { finished in
transitionContext.completeTransition(true)
})
}
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 0.5
}
// MARK: UIViewControllerTransitioningDelegate protocol methods
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = true
return self
}
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = false
return self
}
}
并且,对于视觉参考,这是我的根视图控制器通常的样子:
http://blog.contextures.com/archives/2014/02/27/dynamic-list-with-blank-cells/
并且,对于视觉参考,这是我的根视图控制器在游戏视图中旋转设备(至少一次)时的样子,并返回到根视图控制器。
最后一个注意事项 - 以防它响起任何铃声 - 我使用autolayout和size类来布置我的根视图控制器。
谢谢,
答案 0 :(得分:28)
我遇到了类似的问题,我在导航控制器上为push和pop编写了一个自定义转换。如果在推动后旋转设备,当您弹回到根视图控制器时,它的框架将保持不变。
<强>问题强>
<强>解决方案强>
目标C
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
// ViewController Reference
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// Fix layout bug in iOS 9+
toViewController.view.frame = [transitionContext finalFrameForViewController:toViewController];
// The rest of your code ...
}
Swift 3.0
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// ViewController reference
let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)!
// Fix layout bug in iOS 9+
toViewController.view.frame = transitionContext.finalFrame(for: toViewController)
// The rest of your code ...
}
答案 1 :(得分:5)
我偶然发现了这一点,同时在非身份转换的视图上做了一些手动布局代码。 如果您的视图具有非标识转换,则正常布局代码将失败。
修复,在我的转换委托中是采用转换视图,并在动画中完成回调设置其转换为标识(因为该视图在动画结束时不可见,并且在新视图后面,这具有对外观没有影响)
UIView.animateWithDuration(duration,
delay: 0.0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0,
options: nil,
animations: {
if presenting {
fromView.transform = smallScale
fromView.alpha = smallOpacity
} else {
fromView.transform = bigScale
fromView.alpha = 0
}
},
completion: { completed in
// set transform of now hidden view to identity to prevent breakage during rotation
fromView.transform = CGAffineTransformIdentity
})
答案 2 :(得分:1)
最后,我找到了解决此问题的方法。您需要改进@agilityvision代码。您需要添加BOOL值,类似于closeVCNow,表示您要关闭VC,而在animateTransition:
中,在动画块中执行以下操作:
if (self.closeVCNow) {
toVC.view.transform = CGAffineTransformIdentity;
toVC.view.frame = [transitionContext finalFrameForViewController:toVC];
self.closeVCNow = NO;
}