如何捕获当前视图截图并在代码中重用? (iPhone SDK)

时间:2009-05-18 18:15:22

标签: iphone core-animation rotation

当用户旋转设备时,我正准备从一个UIView过渡到另一个UIView。这本身并不困难。但是,由于我在旋转后显示完全不同的内容,因此UIKit提供的默认动画(旋转当前显示的视图)在概念上是不合适的。

简单地禁用动画并突然交换视图是可以忍受的,但远远低于我正在构建到应用程序其余部分的润色。我更喜欢这样做:

当调用shouldAutorotateToInterfaceOrientation:时,我想在旋转之前抓取一个不透明的视图快照,如果你愿意的话,截取用户视图。然后在完成旋转并且系统已应用视图变换等之后,我可以显示我保存的快照视图,并将我选择的过渡动画设置为我的新视图。完成后,我可以发布我的快照并继续前进。

有没有办法做到这一点并不昂贵?

我能想到的唯一另一个选择是在除默认方向之外的所有方向上返回NO,然后通过应用我自己的动画和变换做出反应。我更喜欢使用系统执行此操作,因为我觉得自己可能会在手动旋转视图中导致“未定义”的键盘行为等。

思想?

4 个答案:

答案 0 :(得分:21)

- (UIImage *)captureView:(UIView *)view {
    CGRect screenRect = [[UIScreen mainScreen] bounds];

    UIGraphicsBeginImageContext(screenRect.size);

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);

    [view.layer renderInContext:ctx];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

在此处找到:

http://discussions.apple.com/thread.jspa?messageID=8358740

答案 1 :(得分:12)

这段代码对我有用

- (UIImage *)captureScreenInRect:(CGRect)captureFrame {
    CALayer *layer;
    layer = self.view.layer;
    UIGraphicsBeginImageContext(self.view.bounds.size); 
    CGContextClipToRect (UIGraphicsGetCurrentContext(),captureFrame);
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return screenImage;
}

答案 2 :(得分:4)

在Mac上这很容易......你只需要-bitmapImageRepForCachingDisplayInRect:,但当然iPhone没有这样的东西。

我想我会通过设置图形上下文并在其上调用[window drawRect:...]来捕获屏幕的当前图像来攻击它。这有点超出规范,因为你真的不应该自己去调用-drawRect:。我对这样的副作用有点紧张,但可能没问题。如果它是您控制的全屏视图,您当然可以从-drawRect:中提取绘图代码,这样您就不会直接调用它。

类似的方法是使用当前CALayer -drawInContext:的{​​{1}}。这可能稍微更“规范”,因为传递你自己的上下文是合法的。但我不知道你是否真的能够正确地获得所有的子视图。可能取决于UIWindow的性质。

无论如何,好问题。也许有人有一个更聪明的解决方案,但这就是我攻击它的方式。

编辑:感谢Rob Terrell和他聪明的UIApplication+TVOut.m,我被介绍了  到私有方法UIGetScreenImage(),它返回一个CGImageRef。如果你愿意去私人方法,这对你来说是个不错的选择。鉴于其名称和功能,它看起来非常稳定,似乎不太可能违反Apple的意图。我还对Air Source进行了非常好的讨论。阅读几个链接的评论。

答案 3 :(得分:1)

我可以保证你[window drawRect:]不起作用。大多数视图都没有实现drawRect:它肯定不像mac那样递归。

drawInContext:也非常多,因为它从根本上要求图层绘制自己,而不是递归子层。 “默认实现什么都不做。”说了一切。

我通过执行以下操作为应用程序商店中的Clif Bar Save Our Snow应用程序实现此功能:

  • 递归地遍历图层层次结构,从每个图层获取内容。如果它闻起来像图像,请使用CGContext方法将其绘制到您的上下文中。
  • 走路时,请确保在递归调用时应用每个图层的转换/位置

是的,屁股上有一个相当大的痛苦。但是,是的,它运作良好并且由Apple完成了:)。