Capture UIImage of UIView including UINavigationBar - ios

I found this code which is quite nice:
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
But I need to capture UINavigationBar as well because i want to use the image as transition layer in my UIStoryboardSegue. Any ideas?

Use your view's window as the view so the navigation bar and status bar will be included, too. If you need to remove the status bar, you'll have to crop the image.

You should take a screenshot of self.navigationController?.view .
That way you get the whole view with navigationBar but without status bar.
if let view = self.navigationController?.view {
let snapshot = view.snapshotViewAfterScreenUpdates(false)
}

instead of view.layer give reference of appdelegate.window.layer it will work.

Wow, really none of these answers work. This is how you do it to get screenshot of everything including navigation controller
-(void) takeScreenshot
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
//its iphone
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480 || result.width == 480)
{
// iPhone Classic
screenRect = CGRectMake(0, 0, 320, 480);
}
if(result.height == 568 || result.width == 568)
{
// iPhone 5
screenRect = CGRectMake(0, 0, 320, 568);
}
}
else
{
//its pad
screenRect = CGRectMake(0, 0, 768, 1024);
}
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
// This code is for high resolution screenshot
UIGraphicsBeginImageContextWithOptions(screenRect.size, NO, 0.0);
//this was pre iOS 7.0
//[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
// iOS 7.x -->
[[[[UIApplication sharedApplication] windows] objectAtIndex:0] drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:YES]; // Set To YES
UIImage *viewImage2 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData* imageData2 = UIImageJPEGRepresentation(viewImage2, 1.0);
NSString* incrementedImgStr2 = [NSString stringWithFormat: #"UserScreenShotPic.jpg"];
// Now we get the full path to the file
NSString* fullPathToFile3 = [documentsDirectory stringByAppendingPathComponent:incrementedImgStr2];
[imageData2 writeToFile:fullPathToFile3 atomically:NO];
}

Related

iOS: Make image width slightly smaller than screen width

I'm having an issue where my image is too big. I need it to be slightly less than what the screen width is.
Here's my controller:
- (void)viewDidLoad {
[super viewDidLoad];
self.imageName = #"goldencoaster";
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"table"]]];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#", self.imageName]];
CGRect bounds;
bounds.origin = CGPointZero;
bounds.size = [[UIScreen mainScreen] bounds].size;
self.coasterImage.bounds = bounds;
self.coasterImage.image = image;
}
However, this returns this when I run the simulator:
How would I get the image to show up slightly smaller than the screen width?
====================================================================
UPDATE
So I took out auto layout as suggested, and updated my controller to look like this:
- (void)viewDidLoad {
[super viewDidLoad];
self.imageName = #"goldencoaster";
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"table"]]];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#", self.imageName]];
CGRect screen = [[UIScreen mainScreen] bounds];
CGRect bounds;
bounds.origin.x = screen.origin.x + 10;
bounds.origin.y = screen.origin.y + 10;
bounds.size.width = screen.size.width - 100;
self.coasterImage.frame = bounds;
self.coasterImage.image = image;
}
However, now my image doesn't show up at all?? Only the background (image with name "table") shows up, but not the goldencoaster.
Try this
- (void)viewDidLoad {
[super viewDidLoad];
self.imageName = #"goldencoaster";
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"table"]]];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#", self.imageName]];
CGRect bounds;
bounds.origin = CGPointZero;
bounds.size = [[UIScreen mainScreen] bounds].size;
self.coasterImage.bounds = bounds;
self.coasterImage.image = image;
self.coasterImage.frame = CGRectMake(20, 0, self.view.frame.size.width-40, self.view.frame.size.height);
self.coasterImage.center = self.coasterImage.superview.center;
}
Swift 3.1
override func viewDidLoad() {
super.viewDidLoad()
imageName = "goldencoaster"
view.backgroundColor = UIColor(patternImage: UIImage(named: "table")!)
let image = UIImage(named: imageName)
var bounds = CGRect()
bounds.origin = CGPoint.zero
bounds.size = (UIScreen.main.bounds).size
coasterImage.bounds = bounds
coasterImage.image = image
coasterImage.frame = CGRect(x: CGFloat(20), y: 0, width: self.view.frame.size.width - CGFloat(40), height: self.view.frame.size.height)
coasterImage.center = (coasterImage.superview?.center)!
}
you can do it with contentMode like
self.coasterImage.contentMode = UIViewContentModeScaleAspectFit;
here are the different contentMode check it from here
UIViewContentModeScaleToFill
UIViewContentModeScaleAspectFit // contents scaled to fit with fixed aspect. remainder is transparent
UIViewContentModeScaleAspectFill // contents scaled to fill with fixed aspect. some portion of content may be clipped.
UIViewContentModeRedraw // redraw on bounds change (calls -setNeedsDisplay)
UIViewContentModeCenter // contents remain same size. positioned adjusted.
UIViewContentModeTop
UIViewContentModeBottom
UIViewContentModeLeft
UIViewContentModeRight
UIViewContentModeTopLeft
UIViewContentModeTopRight
UIViewContentModeBottomLeft
UIViewContentModeBottomRight
Two words: Auto Layout
You want your UI to adapt to different devices, and orientations.
Auto Layout and size classes are designed to handle those needs.
Update:
You're checking screen size and setting bounds. That suggests you're trying to size the view instead of letting Auto Layout constrain it. Auto Layout takes the place of setting frame or bounds. You don't want to mix the two.
If you weren't using autolayout, you will need to edit the image frame. For example if you want to reduce the size in 10 pixels:
- (void)viewDidLoad {
[super viewDidLoad];
self.imageName = #"goldencoaster";
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"table"]]];
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:#"%#", self.imageName]];
CGRect screen = [[UIScreen mainScreen] bounds];
CGRect bounds = CGRectMake(screen.origin.x+10,
screen.origin.y+10,
screen.size.width-20,
screen.size.height-20);
self.coasterImage.center = self.coasterImage.superview.center;
self.coasterImage.frame = bounds;
self.coasterImage.image = image;
}

Adjust iPhone 5 and iPhone 3.5' Screen Size Without Using Autolayout

Hi I am developing an IOS application. I don't use autolayout. If my app run at iPhone 5(4") simulator then showing black top and bottom place. Simulated metricks size also none. What can I do.
Thanx
Just add an splash screen image named Default-568h#2x.png to your project folder black space will be removed automatically.
Use UIView autoresizingMask property.
You can also check screen size and load specific image for iPhone 5.
I use some like this -
#implementation UIImage (iPhone5)
BOOL iPhone5Screen();
+(UIImage*)imageNamed5:(NSString *)name
{
UIImage *retImage = nil;
if (iPhone5Screen()) {
NSString *imageName = [name stringByDeletingPathExtension];
if ([imageName hasPrefix:#"#2x"]){
imageName = [imageName substringToIndex:imageName.length - 3];
}
NSString *iPhone5ImageName = [NSString stringWithFormat:#"%#-568h", imageName];
retImage = [UIImage imageNamed:iPhone5ImageName];
if (retImage) {
return retImage;
}
}
return [UIImage imageNamed:name];
}
BOOL iPhone5Screen()
{
BOOL bRet = NO;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
bRet = NO;
}
else if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 568){
bRet = YES;
}
}
return bRet;
}
#end

IOS UIImage of launch image for current device

is there way to get launch image as UIImage for current device?
or UIImageView with an image
You just need to get Default.png which will have any #2x applied as necessary.
- (UIImage *)splashImage {
return [UIImage imageNamed:#"Default.png"];
}
If you care about getting the iPhone 5 specific one you need to do a height check:
- (UIImage *)splashImage {
if ([[UIScreen mainScreen] bounds].size.height == 568.0){
return [UIImage imageNamed:#"Default-568h.png"];
} else {
return [UIImage imageNamed:name];
}
}
First reduce the name of the launch image using [UIDevice currentDevice] and [UIScreen mainScreen] and then read the image like you would for any other resource image.
[UIImage imageNamed:yourLaunchedImageName];
You can write something like this.
Here we are figuring out what splash image to show (depending on device and scree rotation) and adding it as a subview to our window.
- (void)showSplashImage
{
NSString *imageSuffix = nil;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
imageSuffix = [[UIScreen mainScreen] bounds].size.height >= 568.0f ? #"-568h#2x" : #"#2x";
}
else
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
imageSuffix = UIInterfaceOrientationIsPortrait(orientation) ? #"Portrait" : #"-Landscape";
imageSuffix = [UIScreen mainScreen].scale == 2.0 ? [imageSuffix stringByAppendingString:#"#2x~ipad"] : [imageSuffix stringByAppendingString:#"~ipad"];
}
NSString *launchImageName = [NSString stringWithFormat:#"Default%#.png",imageSuffix];
NSMutableString *path = [[NSMutableString alloc]init];
[path setString:[[NSBundle mainBundle] resourcePath]];
[path setString:[path stringByAppendingPathComponent:launchImageName]];
UIImage * splashImage = [[UIImage alloc] initWithContentsOfFile:path];
UIImageView *imageView = [[UIImageView alloc] initWithImage:splashImage];
imageView.tag = 2;
[self.rootViewController.view addSubview:imageView];
}

UIWebview captures screenshot only for .doc files

Trying to create thumb pictures of documents that has been opened in my app with openurl.
My app can open and save .doc .xls and .pdf file, but when I try to save the screenshot it can correctly save the .doc content, for pdf and xls it only saves a blank white picture.
here are some sample documents I am testing:
.doc,
.pdf,
excel
Here is my code:
-(void)webViewDidFinishLoad:(UIWebView *)webViewCapture
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSLog(#"webViewDidFinishLoad");
NSLog(#"webview %#",webView);
NSLog(#"webViewCapture %#",webViewCapture);
UIGraphicsBeginImageContext(webView.bounds.size);
[webView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Convert UIImage to JPEG
NSData *imgData = UIImageJPEGRepresentation(viewImage, 1);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePathLocal = [documentsDirectory stringByAppendingPathComponent:#"Inbox"];
NSArray *partialDates =[self.imageFilename componentsSeparatedByString:#"."];//split string where - chars are found
NSString* fileDescription= [partialDates objectAtIndex: 0];
//creatre unique name for image _AKIAIVLFQKM11111
NSString *uniqueFileName=[NSString stringWithFormat:#"%#_AKIAIVLFQKM11111_%#.jpeg",fileDescription,[partialDates objectAtIndex: 1]];
NSString *finalFileName= [filePathLocal stringByAppendingPathComponent:uniqueFileName];
NSError *error = nil;
if ([imgData writeToFile:finalFileName options:NSDataWritingAtomic error:&error]) {
// file saved
} else {
// error writing file
NSLog(#"Unable to write PDF to %#. Error: %#", finalFileName, error);
}
}
NSLOG:
webViewDidFinishLoad
webview <UIWebView: 0xaa79070; frame = (0 44; 768 960); autoresize = W+H; layer = <CALayer: 0xaa51000>>
webViewCapture <UIWebView: 0xaa79070; frame = (0 44; 768 960); autoresize = W+H; layer = <CALayer: 0xaa51000>>
Why I cant save real content for other types of documents with above code?
Perhaps it's a problem with the methode you are using to take the screenShot, use the one indicated by apple :
- (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;
}
For more detail : Screen Capture in UIKit Applications
So two ways I can think of working this out are as follows:
1.) Subclass UIWebview and implement drawRect. in drawRect save a screenshot as you have direct access to the graphicsContext. After you have a screenshot assign it to a custom property on the webview. Then whenever you need it, it should be readily available.
2.) take screenshot asynchronously and guarantee that the webview will exist or do proper error handling on the asynch task to handle the event that the webview no longer exists.
I personally would prefer #2 as it pulls some heavy lifting off the main thread and should still work properly.

auto adjusting UI elements for iphone4S and iphone5

After a long search for how to display UI elements correctly on both iphone4S and iphone5.I am now confused as whats the best way to display UI elements in the Xib.Should I use autoresizing Feature in size inspector or should I use auto layout?If I use autoresizing, the image gets distorted.
Moreover ,I have also seen people doing the below
NSString *filename = #"image.png";
CGRect screenRect = [[UIScreen mainScreen] bounds];
if (screenRect.size.height == 568.0f)
filename = [filename stringByReplacingOccurrencesOfString:#".png" withString:#"-568h.png"];
self.imageView.image = [UIImage imageNamed:filename];
Can anybody assist me as how should I proceed with my problem?
I think your method is right but this code will be more cleaner way to put this.
NSString *filename;
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) {
filename = #"image.png";
self.imageView.frame = CGRectMake(0,0,400,300);
} else {
self.imageView.frame = CGRectMake(0,0,300,300);
}
self.imageView.image = [UIImage imageNamed:filename];
And also if you want to change size of imageview accordingly to the iPhone than also you can use this code.

Resources