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];
}
Related
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
I am interested in using a custom overlay for the UIImagePickerController for camera controls that take the entire screen, very similar to what the default Camera app does when switched to the video function.
I have referenced several questions here on SO on this topic, particularly this one, as well as the Apple example on how to use a custom overlay for the UIImagePickerController, but none of them have been able to produce a successful, full-screen result with iOS 7.
So far, this is what the camera UI looks like with the custom overlay (without any buttons):
Note that there is a black bar in the bottom of the screen. I noticed that I could get the black bar removed if I change the cameraAspectRatio to 1, but this distorts the camera zoom as it then has a very zoomed in view. Is there a way to have full screen without either distorting the zoom too much (I understand that a small bit is necessary), and also remove the black bar?
Here is my code that configures the custom overlay:
{
self.imagePickerController.showsCameraControls = NO;
[[NSBundle mainBundle] loadNibNamed:#"overlayView" owner:self options:nil];
self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
self.imagePickerController.cameraOverlayView = self.overlayView;
self.overlayView = nil;
// Device's screen size (ignoring rotation intentionally):
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
float imageWidth = floorf(screenSize.width * cameraAspectRatio);
float scale = ceilf((screenSize.height / imageWidth) * 10.0) / 10.0;
self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);
}
Update:
An additional issue that I noticed is, the picture that is shown in camera preview is always smaller and has less details than the picture that is saved when the method [self.imagePickerController takePicture]. To illustrate:
This is what the keyboard looks like in the camera preview with the black bar below (sorry its a bit shaky):
However, note that the actual captured image in the preview panel has a lot more details as shown here, especially towards the top, as well as both left and right.
My question is, how would be able to set my camera preview so that what the user sees in preview is exactly the image that it will capture and could be shown to them afterwards? Thanks!
Update 2
Here is the entire code in viewDidLoad that sets up the camera controls.
- (void)viewDidLoad
{
[super viewDidLoad];
//Appearance configuration
self.navigationItem.hidesBackButton = YES;
//UIImagePickerController initialization and setup
self.imagePickerController = [[UIImagePickerController alloc] init];
self.imagePickerController.delegate = self;
self.imagePickerController.allowsEditing = NO;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
self.imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera; //if there is a camera avaliable
} else {
self.imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;//otherwise go to the folder
}
self.imagePickerController.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeImage, nil];
if (self.imagePickerController.sourceType == UIImagePickerControllerSourceTypeCamera)
{
self.imagePickerController.showsCameraControls = NO;
[[NSBundle mainBundle] loadNibNamed:#"overlayView" owner:self options:nil];
self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
self.imagePickerController.cameraOverlayView = self.overlayView;
self.overlayView = nil;
// Device's screen size (ignoring rotation intentionally):
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
int heightOffset = 0;
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
{
heightOffset = 120; //whole screen :)
}
float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
float imageWidth = floorf(screenSize.width * cameraAspectRatio);
float scale = ceilf(((screenSize.height + heightOffset) / imageWidth) * 10.0) / 10.0;
self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);
}
}
And in viewWillAppear, I call the image picker view:
BOOL modalPresent = (BOOL)(self.presentedViewController);
//Present the Camera UIImagePicker if no image is taken
if (!appDelegate.imageStorageDictionary[#"picture1"]){
if (modalPresent == NO){ //checks if the UIImagePickerController is modally active
[self presentViewController:self.imagePickerController animated:NO completion:nil];
}
}
After many attempts, this is what worked for me with many thanks to other people's suggestions. The following facts were very helpful to know and keep in mind:
The camera's points resolution is 426 * 320. In order for the camera preview's height to be stretched to the phone's screen height of 568, it needs to be multiplied by a factor of 1.3333 when using CGAffineTransformScale.
Note that the below are hard coded with various numbers based on the iPhone 5's screen resolution in points. They could be improved by using such objects such as screen.height, screen.width and other variables to make it applicable to iPhone 4/4s dimensions as well.
self.imagePickerController.showsCameraControls = NO;
[[NSBundle mainBundle] loadNibNamed:#"overlayView" owner:self options:nil];
self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
self.imagePickerController.cameraOverlayView = self.overlayView;
self.overlayView = nil;
//For iphone 5+
//Camera is 426 * 320. Screen height is 568. Multiply by 1.333 in 5 inch to fill vertical
CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, 71.0); //This slots the preview exactly in the middle of the screen by moving it down 71 points
self.imagePickerController.cameraViewTransform = translate;
CGAffineTransform scale = CGAffineTransformScale(translate, 1.333333, 1.333333);
self.imagePickerController.cameraViewTransform = scale;
In Swift
var picker: UIImagePickerController = UIImagePickerController();
picker.sourceType = UIImagePickerControllerSourceType.Camera;
picker.showsCameraControls = false;
var screenBounds: CGSize = UIScreen.mainScreen().bounds.size;
var scale = screenBounds.height / screenBounds.width;
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform, scale, scale);
Make sure that you account for 20px status bar change in iOS7. If you are facing a 20px black screen at bottom of the screen then this will be your issue. You can check that whether the app is running in ios7 or not by one of these preprocessors
#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
And you can make following changes to your code and see if it works
{
self.imagePickerController.showsCameraControls = NO;
[[NSBundle mainBundle] loadNibNamed:#"overlayView" owner:self options:nil];
self.overlayView.frame = self.imagePickerController.cameraOverlayView.frame;
self.imagePickerController.cameraOverlayView = self.overlayView;
self.overlayView = nil;
// Device's screen size (ignoring rotation intentionally):
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
int heightOffset = 0;
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
{
heightOffset = 20;
}
float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
float imageWidth = floorf(screenSize.width * cameraAspectRatio);
float scale = ceilf(((screenSize.height + heightOffset) / imageWidth) * 10.0) / 10.0;
self.imagePickerController.cameraViewTransform = CGAffineTransformMakeScale(scale, scale);
}
Please let me know if it works. I haven't coded it to test.
Because the screen aspect ratio is different than the 4/3 ratio of the camera itself, you need (as you mentioned) to slightly crop the edges in order to have the image extend to the bottom.
In order to do that, you need to have the width be wide enough so that the height can be the full screen. So, your image width and height must be:
float cameraAspectRatio = 4.0 / 3.0; //! Note: 4.0 and 4.0 works
float imageWidth = screenSize.height / cameraAspectRatio;
You'll also probably want the view presenting the camera image to be that width that extends off both sides of the screen.
There is a way easier method to get your overlay fullscreen at least tested in iOS 9.
let view = ... your overlayView
let bounds = UIScreen.mainScreen().bounds
view.center = CGPoint(x: bounds.midX, y: bounds.midY)
view.bounds = bounds
self.imagePicker.cameraOverlayView = view
I don't know why you use screen size. Just try this simple code:
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])
{
UIImagePickerController *controller = [[UIImagePickerController alloc] init];
controller.sourceType = UIImagePickerControllerSourceTypeCamera;
controller.allowsEditing = NO;
controller.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:
UIImagePickerControllerSourceTypeCamera];
controller.delegate = self;
[self presentViewController:controller animated:NO completion:^{}];
}
Try this code to maintain your resultant image in custom size. I got result by using custom method for getting resultant image as custom size.
First create IBOutlet for UIImageview.
-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
NSString *mediaType = info[UIImagePickerControllerMediaType];
[self dismissViewControllerAnimated:YES completion:nil];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
OriginalImage=info[UIImagePickerControllerOriginalImage];
image = info[UIImagePickerControllerOriginalImage];
//----------------------------------------
imageview.image = image; //------------- additional method for custom image size
self resizeImage];
//-----------------------------------------
if (_newMedia)
UIImageWriteToSavedPhotosAlbum(image,self,#selector(image:finishedSavingWithError:contextInfo:),nil);
}
else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie])
{
// Code here to support video if enabled
}
}
//---- Resize the original image by using custom method----------------------
-(void)resizeImage
{
UIImage *resizeImage = imageview.image;
float width = 320;
float height = 320;
CGSize newSize = CGSizeMake(320,320);
UIGraphicsBeginImageContextWithOptions(newSize,NO,0.0);
CGRect rect = CGRectMake(0, 0, width, height);
float widthRatio = resizeImage.size.width / width;
float heightRatio = resizeImage.size.height / height;
float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;
width = resizeImage.size.width / divisor;
height = resizeImage.size.height / divisor;
rect.size.width = width;
rect.size.height = height;
//indent in case of width or height difference
float offset = (width - height) / 2;
if (offset > 0) {
rect.origin.y = offset;
}
else {
rect.origin.x = -offset;
}
[resizeImage drawInRect: rect];
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageview.image = smallImage;
imageview.contentMode = UIViewContentModeScaleAspectFit;
}
To solve a similar problem, I instantiated a ViewController from storyboard and used the controller's view as camera overlay.
I don't know if it's what you're looking for, but i used the following code:
UIImagePickerController *globalPicker = [[UIImagePickerController alloc] init];
globalPicker.delegate = self;
globalPicker.sourceType = UIImagePickerControllerSourceTypeCamera;controller=[self.storyboard instantiateViewControllerWithIdentifier:#"myVC"];
overlayView = controller.view;
UIView *cameraView=[[UIView alloc] initWithFrame:self.view.bounds];
[cameraView addSubview:overlayView];
[globalPicker setCameraOverlayView:cameraView];
Try this code, it works fine for me
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraUI.showsCameraControls = NO;
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
float cameraAspectRatio = 4.0 / 3.0;
float imageHeight = floorf(screenSize.width * cameraAspectRatio);
float scale = screenSize.height / imageHeight;
float trans = (screenSize.height - imageHeight)/2;
CGAffineTransform translate = CGAffineTransformMakeTranslation(0.0, trans);
CGAffineTransform final = CGAffineTransformScale(translate, scale, scale);
cameraUI.cameraViewTransform = final
;
cameraUI.delegate = self;
[self presentViewController:cameraUI animated:YES completion:nil];
This code assumes that the aspect of the original camera preview area is 4:3.
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.
I have Default splash screens with the names:
Default-568h#2x.png, Default-Portrait.png, Default.png, Default#2x.png and so on for all types of devices.
I know that the system automatically selects the appropriate splash screen for the specific device and displays it.
The questions: is it possible to know which image the system selected? How to load the appropriate image selected by the system to the UIimageView.
I tried this:
UIImageView *splashView=[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight)];
splashView.image=[UIImage imageNamed:#"Default.png"];
But it loads only the image with name Default.png for all types of devices(iPhone 4, 5, iPad).
Do i need to manage it manually? I mean to load the appropriate image after identifying the device type?
I found this question after running into the same problem. Seems that if you use [UIImage imagedNamed:#"Default"]; iOS will detect retina versus non-retina and apply the #2x but it won't detect an iPhone 5 and apply the -568h
The solution I came up with was to write a category on UIImage that checks the main window's height and returns the appropriate image if it exists:
#interface UIImage (Compatible)
+ (UIImage *)compatibleImageNamed:(NSString *)name;
#end
#implementation UIImage (Compatible)
+ (UIImage *)compatibleImageNamed:(NSString *)name {
if ([[UIScreen mainScreen] bounds].size.height==568.0){
NSString *extension = [name pathExtension];
NSString *iPhone5Name = [[name stringByDeletingPathExtension] stringByAppendingString:#"-568h"];
if (extension.length!=0)
iPhone5Name = [iPhone5Name stringByAppendingPathExtension:extension];
UIImage *image = [UIImage imageNamed:iPhone5Name];
if (image)
return image;
}
return [UIImage imageNamed:name];
}
#end
Then wherever I know I want to load an image that also has an iPhone 5 version I use:
[UIImage compatibleImageNamed:#"MyImage"];
I did it manually for all splash screens:
CGRect screenRect = [[UIScreen mainScreen] bounds];
float screenWidth = screenRect.size.width;
float screenHeight = screenRect.size.height;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
splashView=[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight)];
if (screenHeight==568.0) {
splashView.image=[UIImage imageNamed:#"Default-568h#2x.png"];//iPhone 5
}else{
splashView.image=[UIImage imageNamed:#"Default.png"]; //other iPhones
}
} else {
splashView=[[UIImageView alloc] initWithFrame:CGRectMake(0, 20, screenWidth, screenHeight-20)];
splashView.image=[UIImage imageNamed:#"Default-Portrait.png"];// iPads
}
EDIT: check this and also this out.
U how use this line to provide splash screen whether u have retina or non-retina display
UIImageView *splashView =[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Default.png"]];
Application detects device display takes image accordingly.
If device has retina display then it takes Default#2x.png automatically.
You should change this:
[UIImage imageNamed:#"Default.png"];
to
[UIImage imageNamed:#"Default"];
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];
}