4

I'm trying to take a screenshot using this code:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor lightGrayColor];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidAppear:(BOOL)animated{
    UIImageWriteToSavedPhotosAlbum([self screenshot], self, @selector(image: didFinishSavingWithError:contextInfo:), nil);
}

- (UIImage*)screenshot
{
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
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 *image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return image;
}

But the saved image has the status bar whited out, including the signal, time, and battery. How could I take the screenshot including the content of status bar? enter image description here

rptwsthi
  • 10,094
  • 10
  • 68
  • 109
lu yuan
  • 7,207
  • 9
  • 44
  • 78

3 Answers3

1

Hide the status bar before taking screenshot as follows:

([[UIApplication sharedApplication] setStatusBarHidden:YES];)

Piccolo
  • 1,612
  • 4
  • 22
  • 38
Fahri Azimov
  • 11,470
  • 2
  • 21
  • 29
1

(Tested with iOS 7 and autolayout)

I use the simulator 'take screenshot' feature combined with some conditional code compilation. By uncommenting a #define I can quickly switch to 'take screenshot' mode for my launch screen

The main trick is to hide the status bar when the view controller of your opening screen appears, but with a very long animation, so you have plenty of time to hit the screenshot command in the simulator, which places a screenshot right on your desktop (or take a screenshot on the device if you prefer that).

Using the code below, the status bar disappears immediately thanks to the 'UIStatusBarAnimationNone', but the 'sliding off screen' is animated over a very long period (5000.0 seconds in the code below). So before the bar starts 'moving' 1 point out of the 20 points in vertical size, you have roughly 5000/20 = 250 seconds to take your screenshot (and some coffee).

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
    #ifdef kTAKE_LAUNCHIMAGE_SCREENSHOT
       return UIStatusBarAnimationNone;
    #else
       return UIStatusBarAnimationSlide;
    #endif
}

- (void)removeStatusBarAnimated
{
    #ifdef kTAKE_LAUNCHIMAGE_SCREENSHOT
        [UIView animateWithDuration:5000.0 animations:^{
            [self setNeedsStatusBarAppearanceUpdate];
        }];
    #else
        [UIView animateWithDuration:2.0 animations:^{
            [self setNeedsStatusBarAppearanceUpdate];
        }];
    #endif
}

for more information on taking control of the status bar in iOS 7, check my answer and code here :

https://stackoverflow.com/a/20594717/1869369

Community
  • 1
  • 1
Ronny Webers
  • 5,244
  • 4
  • 28
  • 24
  • Thanks for the edit Anindya, I don't know how to msg you personally, so I'll ask my question here : I always have trouble copy/pasting code from Xcode to stack overflow - layout is terrible, however I use the 'insert code button' and then 'paste' my code. What am I doing wrong? – Ronny Webers Mar 20 '14 at 13:16
0

This is a solution without hiding the status bar, simply use the correct bounds and note that the y offset should be negative, here "map" is the a view that fills the screen below the status bar: (Code is written inside a ViewController)

UIGraphicsBeginImageContextWithOptions(self.map.bounds.size, NO, [UIScreen mainScreen].scale);
CGRect bounds = CGRectMake(0, -1*(self.view.bounds.size.height-self.map.bounds.size.height), self.map.bounds.size.width, self.map.bounds.size.height);

BOOL success = [ self.view drawViewHierarchyInRect:bounds afterScreenUpdates:YES];

UIImage* image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();
Nech
  • 331
  • 3
  • 11