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

发布于 2024-07-19 11:01:06 字数 507 浏览 2 评论 0原文

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

简单地禁用动画并突然交换视图是可以忍受的,但远远低于我在应用程序的其余部分中构建的完善程度。 我想做的是:

当调用 shouldAutorotateToInterfaceOrientation: 时,我想获取旋转之前的用户视图的不透明视图快照(如果愿意的话)。 然后,在旋转完成并且系统应用了视图变换等之后,我可以显示我保存的快照视图,并将我选择的动画转换到新视图。 完成后,我可以发布我的快照并继续。

有没有一种方法可以做到这一点并且不昂贵?

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

什么想法?

I am attemting to transition from one UIView to another, when the user rotates the device. This, in of itself, is not difficult. However, since I am displaying completely different content after the rotation, the default animation provided by UIKit (rotating the currently displayed view) is inappropriate conceptually.

Simply disabling the animation and swapping the views suddenly is tolerable, but is far below the polish I'm building into the rest of the app. What I would prefer to do is this:

When shouldAutorotateToInterfaceOrientation: is called, I would like to grab an opaque view snapshot, a screenshot if you will, of the user view before rotation. Then after the rotation is completed and the system has applied the view transforms etc, I can show the snapshot view I saved and animate a transition of my choice to my new view. After it is completed, I can release my snapshot and move on.

Is there a way to do this that is not expensive?

The only other option I can think of is to return NO on all orientations other than my default one, and then react by applying my own animations and transforms. I'd prefer to use the system to do this however, as I feel it is likely doing it myself could cause "undefined" keyboard behavior in the manually rotated view, etc.

Thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沩ん囻菔务 2024-07-26 11:01:06
- (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

- (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;
}

Found this here :

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

红尘作伴 2024-07-26 11:01:06

这段代码对我有用

- (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;
}

This code worked for me

- (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;
}
抽个烟儿 2024-07-26 11:01:06

在 Mac 上,这非常简单...您只需要 -bitmapImageRepForCachingDisplayInRect:,但 iPhone 当然没有这样的东西。

我想我可以通过设置图形上下文并在其上调用 [window drawRect:...] 来捕获屏幕的当前图像来解决此问题。 这有点不符合规范,因为您实际上不应该自己调用 -drawRect: 。 我会有点担心这样做的副作用,但可能没问题。 如果它是您控制的全屏视图,您当然可以将绘图代码从 -drawRect: 中提升出来,这样您就不会直接调用它。

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

不管怎样,这是个好问题。 也许有人有更聪明的解决方案,但这就是我攻击它的方式。

编辑:感谢 Rob Terrell 和他聪明的 UIApplication +TVOut.m,我被介绍了
到返回 CGImageRef 的私有方法 UIGetScreenImage()。 如果您愿意使用私有方法,这对您来说是一个不错的选择。 考虑到它的名称和功能,它对我来说看起来相当稳定,并且似乎不太可能违反苹果的意图。 我还在 上遇到了一个非常好的讨论空气源。 通读评论中的几个链接。

On Mac this is so easy... you just need -bitmapImageRepForCachingDisplayInRect:, but of course iPhone has no such thing.

I think I would attack this by setting up a graphics context and calling [window drawRect:...] on it to capture the current image of the screen. This is a bit out of spec, because you're not really supposed to go calling -drawRect: yourself. I'd be a bit nervous of side-effects on doing this, but it may be fine. If it's a full-screen view you control, you could of course hoist the drawing code out of -drawRect: so you're not calling that directly.

A similar approach would be to use CALayer -drawInContext: of the current -presentationLayer. That might be slightly more "in spec" since it's legal to pass that your own context. But I don't know if you'd actually be able to get all the sub-views correctly. Might depend on the nature of your UIWindow.

Anyway, great question. Maybe someone has a more clever solution, but this is the way I'd attack it.

EDIT: Thanks to Rob Terrell, and his clever UIApplication+TVOut.m, I was introduced
to the private method UIGetScreenImage() which returns a CGImageRef. If you're willing to go to private methods, that's a nice option for you. Given its name and functionality, it looks pretty stable to me and seems unlikely to violate Apple's intent. I also bumped into a pretty nice discussion on Air Source. Read through the comments for several links.

烟火散人牵绊 2024-07-26 11:01:06

我可以保证你 [window drawRect:] 不会工作。 大多数视图不实现drawRect:并且它肯定不像Mac上那样是递归的。

drawInContext: 也几乎是类似的,因为它从根本上要求图层绘制自身,而不是递归地绘制其子图层。 “默认实现什么也不做。” 说明了一切。

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

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

,这是一个相当大的痛苦。 但是,是的,它运行得很好,并且被苹果公司通过了:)。

I can guarantee you [window drawRect:] won't work. Most views don't implement drawRect: and it's certainly not recursive like on the mac.

drawInContext: is also pretty much hosed simalarly, as it's fundamentally asking the layer to draw itself, not its sublayers recursively. "Default implementation does nothing." says it all.

I implementing this for the Clif Bar Save Our Snow app in the app store by doing the following:

  • Walk the layer hierarchy recursively, getting the contents from each layer. If it smells like an image, use the CGContext methods to draw it into your context.
  • While walking, make sure to apply the transformations/positions of each layer as you call recursively

Yes, a rather large pain in the ass. But yes, it works pretty well and got through by Apple :).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文