我有一个自定义segue,我试图做反向标准的“Cover Vertical”segue过渡。我认为这应该有效:
UIView *srcView = ((UIViewController *)self.sourceViewController).view; UIView *dstView = ((UIViewController *)self.destinationViewController).view; [dstView setFrame:CGRectMake(0, 0, srcView.window.bounds.size.width, srcView.window.bounds.size.height)]; [srcView.window insertSubview:dstView belowSubview:srcView]; [UIView animateWithDuration:0.3 animations:^{ srcView.center = CGPointMake(srcView.center.x - srcView.frame.size.width, srcView.center.y); } completion:^(BOOL finished){ [srcView removeFromSuperview]; } ];
问题是即使应用中的每个其他视图都是横向,目标视图也会以纵向显示。此外,x和y坐标相反。为什么会这样?
我在每个视图控制器中都设置了shouldAutorotateToInterfaceOrientation
,但这没有帮助。我可以用CGAffineTransformMakeRotation
旋转视图,但这似乎不是正确的事情;一方面,坐标仍然会被颠倒。
更新
我尝试使用CGAffineTransformRotate
旋转视图,但看起来很荒谬。大多数背景显示为黑色。我不认为这是它的工作方式。
答案 0 :(得分:3)
由于我无法在控制器交换之前获得正确的方向和目标视图框架,我确实颠倒了这个过程:
以下是完整的代码:
#include <QuartzCore/QuartzCore.h>
@implementation HorizontalSwipingSegue
- (void) perform {
UIViewController *source = self.sourceViewController;
UIViewController *destination = self.destinationViewController;
UIView *sourceView = source.view;
UIView *destinationView = destination.view;
// Create a UIImageView with the contents of the source
UIGraphicsBeginImageContext(sourceView.bounds.size);
[sourceView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *sourceImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *sourceImageView = [[UIImageView alloc] initWithImage:sourceImage];
[[self sourceViewController] presentViewController:[self destinationViewController] animated:NO completion:NULL];
CGPoint destinationViewFinalCenter = CGPointMake(destinationView.center.x, destinationView.center.y);
CGFloat deltaX = destinationView.frame.size.width;
CGFloat deltaY = destinationView.frame.size.height;
switch (((UIViewController *)self.sourceViewController).interfaceOrientation) {
case UIDeviceOrientationPortrait:
destinationView.center = CGPointMake(destinationView.center.x - deltaX, destinationView.center.y);
sourceImageView.center = CGPointMake(sourceImageView.center.x + deltaX, sourceImageView.center.y);
break;
case UIDeviceOrientationPortraitUpsideDown:
destinationView.center = CGPointMake(destinationView.center.x + deltaX, destinationView.center.y);
sourceImageView.center = CGPointMake(sourceImageView.center.x + deltaX, sourceImageView.center.y);
break;
case UIDeviceOrientationLandscapeLeft:
destinationView.center = CGPointMake(destinationView.center.x, destinationView.center.y - deltaY);
sourceImageView.center = CGPointMake(sourceImageView.center.x + deltaY, sourceImageView.center.y);
break;
case UIDeviceOrientationLandscapeRight:
destinationView.center = CGPointMake(destinationView.center.x, destinationView.center.y + deltaY);
sourceImageView.center = CGPointMake(sourceImageView.center.x + deltaY, sourceImageView.center.y);
break;
}
[destinationView addSubview:sourceImageView];
[UIView animateWithDuration:0.6f
animations:^{
destinationView.center = destinationViewFinalCenter;
}
completion:^(BOOL finished){
[sourceImageView removeFromSuperview];
}];
}
@end
答案 1 :(得分:1)
更新的答案:
确保正确设置dstView的框架。我想你会有更好的运气:
dstView.frame = srcView.frame;
而不是:
[dstView setFrame:CGRectMake(0, 0, srcView.window.bounds.size.width, srcView.window.bounds.size.height)];
bounds
属性不会像frame
那样对方向更改做出反应。
答案 2 :(得分:1)
显然,这比我想做的更容易。这是有效的:
- (void)perform {
UIViewController *src = (UIViewController *)self.sourceViewController;
[src dismissViewControllerAnimated:YES completion:^(void){ [src.view removeFromSuperview]; }];
}
希望这有助于其他人。
答案 3 :(得分:0)
替换
[srcView insertSubview:dstView belowSubview:srcView];
与
[srcView insertSubview:dstView atIndex:0];
答案 4 :(得分:0)
如果您只是将另一个视图控制器的视图添加到视图层次结构中,那么该视图控制器将不会获得有关设备方向的任何信息,因此它将以默认配置显示视图。您还需要使用描述here的包含方法将视图控制器添加到视图控制器层次结构中。完成后,您还需要将其从层次结构中删除。
关于这个主题还有几个很好的WWDC会谈,一个来自2011年,名为“实施视图控制器遏制”,一个来自今年,视图控制器的演变。