以编程方式在iOS中捕获状态栏的完整屏幕截图

Uma*_*oon 14 objective-c uiwindow ios uiscreen

我正在使用此代码捕获屏幕截图并将其保存到相册中.

-(void)TakeScreenshotAndSaveToPhotoAlbum
{
   UIWindow *window = [UIApplication sharedApplication].keyWindow;

   if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
       UIGraphicsBeginImageContextWithOptions(window.bounds.size, NO, [UIScreen mainScreen].scale);
   else
       UIGraphicsBeginImageContext(window.bounds.size);

   [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
   UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}
Run Code Online (Sandbox Code Playgroud)

但问题是每当截图保存时,我都看不到iPhone的状态栏.相反,底部会出现一个空白区域.如下图所示: 在此输入图像描述

我究竟做错了什么?

jrt*_*ton 18

状态栏实际上在它自己的UIWindow中,在您的代码中,您只渲染viewcontroller的视图,但不包含此视图.

"官方"截图方法在这里,但现在似乎已被Apple删除,可能是因为它已经过时了.

在iOS 7下,现在有一种新方法UIScreen可以获取包含整个屏幕内容的视图:

- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个视图,然后您可以在屏幕上操作各种视觉效果.

如果要将视图层次结构绘制到上下文中,则需要遍历application([[UIApplication sharedApplication] windows])的窗口并在每个窗口上调用此方法:

- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates
Run Code Online (Sandbox Code Playgroud)

可以将上述两种方法结合起来并获取快照视图,然后在快照上使用上述方法绘制它.

  • 所以我猜测正确的答案是,绝对没有办法获取状态栏的屏幕截图? (4认同)
  • 如果将这两种方法结合使用,您将获得黑色图像,显然快照视图无法以这种方式绘制.即使您在屏幕上迭代窗口,也无法捕获状态栏.可悲的是. (2认同)

pai*_*aiv 7

建议的"官方"屏幕截图方法不捕获状态栏(它不在应用程序的Windows列表中).在iOS 5上测试过.

我相信,这是出于安全原因,但在文档中没有提到它.

我建议两个选择:

  • 从应用程序的资源中绘制存根状态栏图像(可选择更新时间指示器);
  • 仅捕获您的视图,没有状态栏,或之后修剪图像(图像大小将与标准设备分辨率不同); 状态栏框架是从应用程序对象的相应属性中得知的.


小智 6

这是我的代码,用于截取屏幕截图并将其存储为NSData(在IBAction中).使用sotred NSData,您可以共享或发送电子邮件或任何想做的事情

CGSize imageSize = [[UIScreen mainScreen] bounds].size;
        if (NULL != UIGraphicsBeginImageContextWithOptions)
            UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
        else
            UIGraphicsBeginImageContext(imageSize);

        CGContextRef context = UIGraphicsGetCurrentContext();

        // Iterate over every window from back to front
        for (UIWindow *window in [[UIApplication sharedApplication] windows])
        {
            if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen])
            {
                // -renderInContext: renders in the coordinate space of the layer,
                // so we must first apply the layer's geometry to the graphics context
                CGContextSaveGState(context);
                // Center the context around the window's anchor point
                CGContextTranslateCTM(context, [window center].x, [window center].y);
                // Apply the window's transform about the anchor point
                CGContextConcatCTM(context, [window transform]);
                // Offset by the portion of the bounds left of and above the anchor point
                CGContextTranslateCTM(context,
                                      -[window bounds].size.width * [[window layer] anchorPoint].x,
                                      -[window bounds].size.height * [[window layer] anchorPoint].y);

                // Render the layer hierarchy to the current context
                [[window layer] renderInContext:context];

                // Restore the context
                CGContextRestoreGState(context);
            }
        }

        // Retrieve the screenshot image
        UIImage *imageForEmail = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();

    NSData *imageDataForEmail = UIImageJPEGRepresentation(imageForEmail, 1.0);
Run Code Online (Sandbox Code Playgroud)

  • 尽管存在抄袭的指控,但在此背景下获得答案很好,而不仅仅是我未来或未来的工作链接. (2认同)