Jas*_*ore 18 uiviewcontroller modalviewcontroller ios7
我有一个自定义动画UIViewController转换,似乎iOS中存在一个错误,它以横向方向搞砸了布局.在主要的动画方法中,我给出了混合的横向和纵向视图.(在肖像中,视图都是人像,所以没问题.)
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
{
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *containerView = [transitionContext containerView];
// fromViewController.view => landscape, transform
// toViewController.view => portrait, transform
// containerView => portrait, no transform
[containerView addSubview:toViewController.view];
// ...animation... //
}
Run Code Online (Sandbox Code Playgroud)
我知道frame当视图有变换时属性不可靠 - 所以我猜这是问题的根源.在横向模式下,to/from viewControllers视图具有90度顺时针变换[0 -1 1 0].我已经尝试使用边界/中心来调整视图的大小和位置,以及删除变换然后重新应用它,但是UIKit与我打架并且坚持将视图显示为肖像.烦!
在屏幕截图中,深灰色是UIWindow背景,红色是添加的模态视图控制器,应覆盖整个屏幕.
有人找到了解决方法吗?
Jas*_*ore 17
好的,修复非常简单:
在将视图添加到容器之前,将toViewController框架设置为容器.
toViewController.view.frame = containerView.frame;
[containerView addSubview:toViewController.view];
Run Code Online (Sandbox Code Playgroud)
更新:您仍然存在一个限制,即您不知道框架的方向.它最初是肖像,但在屏幕上显示时会延伸到横向.如果您想要从右侧滑动视图,在横向中它可能会从"顶部"滑入(如果查看其他横向,则滑入底部!)
Dan*_*sko 13
我遇到了这个问题,我只是觉得上述解决方案没有做到这一点.我提出了一个不需要hacky代码和硬编码帧的解决方案.
UIView有一个很棒的功能,可以将CGRect转换为另一个(即; +[UIView convertRect:fromView:])的坐标空间.因此,我希望详细介绍一种可以在任何方向上实现此效果的简单方法,而无需任何硬编码值.在这个例子中,我们想要一个简单的动画,从屏幕右侧滑动视图.
所以在我们的动画师中animateTransition(:)我们可以简单地执行以下操作:
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let toView = toViewController.view
let fromView = fromViewController.view
let containerView = transitionContext.containerView()
if(isPresenting) {
//now we want to slide in from the right
let startingRect = CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0)
toView.frame = containerView.convertRect(startingRect, fromView:fromView);
containerView.addSubview(toView)
let destinationRect = containerView.convertRect(fromView.bounds, fromView: fromView)
UIView.animateWithDuration(transitionDuration(transitionContext),
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.7,
options: .BeginFromCurrentState,
animations: { () -> Void in
toView.frame = destinationRect
}, completion: { (complete) -> Void in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
})
} else {
//we want to slide out to the right
let endingRect = containerView.convertRect(CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0), fromView: fromView)
UIView.animateWithDuration(transitionDuration(transitionContext),
delay: 0,
usingSpringWithDamping: 0.7,
initialSpringVelocity: 0.7,
options: .BeginFromCurrentState,
animations: { () -> Void in
fromView.frame = endingRect
}, completion: { (complete) -> Void in
if !transitionContext.transitionWasCancelled() {
fromView.removeFromSuperview()
}
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
})
}
}
Run Code Online (Sandbox Code Playgroud)
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *toView = toViewController.view;
UIView *fromView = fromViewController.view;
UIView *containerView = [transitionContext containerView];
if(self.isPresenting) {
//now we want to slide in from the right
CGRect startingRect = CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0);
toView.frame = [containerView convertRect:startingRect fromView:fromView];
[containerView addSubview:toView];
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
toView.frame = [containerView convertRect:fromView.bounds
fromView:fromView];
}
completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
} else {
//we want to slide out to the right
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
CGRect endingRect = CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0);
fromView.frame = [containerView convertRect:endingRect fromView:fromView];
}
completion:^(BOOL finished) {
[fromView removeFromSuperview];
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助那些在同一条船上来到这里的人(如果确实如此,那么投票不会受到伤害:))
现有的答案是部分方式,但不是所有方式(我们希望在两个设备上都有适当的帧和旋转处理,所有方向,用于动画和交互式转换).
这篇博文有助于:
它引用了Apple支持人员陈述问题的真实性质:
"对于自定义表示过渡,我们在窗口和windows rootViewController视图之间设置了一个中间视图.这个视图是你在其中执行动画的容器视图.由于iOS上自动旋转的实现细节,当界面旋转时,我们应用一个仿射变换到windows rootViewController的视图并相应地修改它的边界.因为containerView从窗口而不是根视图控制器的视图继承它的尺寸,所以它总是处于纵向方向.
"如果您的演示动画取决于呈现视图控制器的方向,则需要检测呈现视图控制器的方向并适当地修改动画.系统会将正确的变换应用于传入的视图控制器,但您需要动画师需要配置传入视图控制器的帧."
但它没有解决交互式过渡问题.
我在这里找到了一个完整的问题解决方案:
https://github.com/alfiehanssen/Cards
实质上,您需要根据viewControllers之一(toViewController或fromViewController)的方向计算viewControllers的帧,而不是transitionContext的containerView的边界.