子视图有错误的方向

时间:2012-07-26 15:04:40

标签: objective-c ios uistoryboardsegue

我有一个自定义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旋转视图,但看起来很荒谬。大多数背景显示为黑色。我不认为这是它的工作方式。

5 个答案:

答案 0 :(得分:3)

由于我无法在控制器交换之前获得正确的方向和目标视图框架,我确实颠倒了这个过程:

  1. 将源视图另存为图像(请参阅Remove custom UIStoryboardSegue with custom animation);
  2. 切换当前控制器[presentViewController:...];
  3. 然后,使用(现在正确的)目标视图嵌入已保存的源图像来制作动画。
  4. 以下是完整的代码:

    #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年,名为“实施视图控制器遏制”,一个来自今年,视图控制器的演变。