How to use xcassets/universal background images for different iPhones/iPads? - ios

I would like to display a different background for each different device (i.e. iPhone 4S, iPhone 5, iPhone6, iPhone 6Plus etc.). I am not talking about launch images but app's backgrounds that will be displayed while using the app.
I have added the following code in my ViewController:
var bgImage = UIImage(named: "main_bg");
var imageView = UIImageView(frame: self.view.bounds);
imageView.image = bgImage
self.view.addSubview(imageView)
self.view.sendSubviewToBack(imageView)
And I am ready to add the assets into the Images.xcassets catalog.
This is what I see when I create a new "Image set"
Therefore, I am trying to match the assets with each different device.
Thanks to this question: universal image support I now know that these devices will access the following images:
iPhone 3 -> 1x (image size: 320x480px)
iPhone 4/4S/6 -> 2x (image size: 640x960px)
iPhone 5/5c/5s/iPod Touch -> Retina 4 2x (image size: 640x1336)
iPhone 6 Plus -> 3x (image size: 1242 x 2208)
My question is, how can iPhones 4/4s and 6 access the same image if, clearly, it's not in the right size for both devices?
Thank you

Try to check this answer:
How to handle image scale on all the available iPhone resolutions?
You can use this code to configure a different image as well:
NSNumber *screenWidth = #([UIScreen mainScreen].bounds.size.width);
NSString *imageName = [NSString stringWithFormat:#"name-%#w", screenWidth];
UIImage *image = [UIImage imageNamed:imageName];

Related

How to get real image.size in diff devices(iphone4s/5s/6/iPhone6+)?

The original image file PX as (24*50);
File name as
"icon_detail_black.png"
in my project;
Using this code:
image_ = [UIImage imageNamed:#"icon_detail_black"];
Then the result in diff devices:
iphone 4s image_.size = (24*50)
iphone 5s image_.size = (12*25)
iphone 6 image_.size = (12*25)
iphone 6+ image_.size = (8*16.666666667)
why?
can we get the real original size?
i want get image size as is (24*50) (original image size). did have any solution? thanks
Note:
The "icon_detail_black.png" file as is "#3x" file,
i just set name "icon_detail_black.png",
i don't want to add the other file :
"icon_detail_black.png" and
"icon_detail_black#2x.png"
i want just using one file (#3x) instead of three file, then using scale image to show in iphone4s/5s/6+ all of diff devices. so i need get the original image size.
Solution 20150528:
UIImage *image_s = [UIImage imageNamed:#"DefaultImage_JNYJScrollImage"];
CGSize size_ = image_s.size;
CGFloat float_ = image_s.scale;
size_.width = size_.width*float_;
size_.height = size_.height*float_;
Thanks all.
File name "icon_detail_black.png" results in the IDE rendering this dimension for 1x.
When you move to 5s, is scales to resolution for 2x, then for 6, same, and the for 6+ it scales it for 3x.
You should have one image for 4s, one for 5s-6 ending in #2x and one for 6+ ending in #3x, each with the proper resolutions for the device.
For your case in particular, you should have:
"icon_detail_black.png" 24x50px
"icon_detail_black#2x.png" 48x100px
"icon_detail_black#3x.png" 72x150px
added to your project (considering the 24x50) is the resolution for 1x
Name the icon as shown for 1x , 2x and 3x as shown:
icon_detail_black-50w (#1x)
icon_detail_black-100w (#2x)
icon_detail_black-150w (#3x)
Then figure out what image you need at runtime:
NSNumber *screenWidth = #([UIScreen mainScreen].bounds.size.width);
NSString *imageName = [NSString stringWithFormat:#"name-%#w", screenWidth];
UIImage *image = [UIImage imageNamed:imageName];
4 Details: see question details:
UIImage *image_s = [UIImage imageNamed:#"DefaultImage_JNYJScrollImage"];
CGSize size_ = image_s.size;
CGFloat float_ = image_s.scale;
size_.width = size_.width*float_;
size_.height = size_.height*float_;

Xcode asset catalog support for 3.5", 4", and 4.7" #2x images?

Xcode offers asset buckets for 1x, 2x, 4" 2x, and 3x assets. My fullscreen assets are all wonky with this configuration, because the 2x bucket is used for 3.5" and 4.7" screens. Currently I have a UIImage category that introspects the current screen size, and selects a "*-3.5" asset if the device seems to be 3.5".
This is clunky and not cool. Seeing that Xcode caters to all the different device sizes for their LaunchImage asset, I was hoping there was some way to supply device specific assets for non launch image assets without resorting to code.
I have reported a bug to Apple about this since mid November 2014 and I just noticed they marked it as No Value... which gives me the impression Apple has omitted an additional slot for iPhone 6 on purpose. My guess is they now want the 2x slot to be used for iPhone 6, and maybe they're reducing support to iPhone 4s as it's getting old.
If you really want to keep supporting the iPhone 4s, I'd suggest to use iPhone 6 sized images in the 2x slot, and then use the following method to load your images:
+(UIImage *)loadImageNamed:(NSString *)imageName
{
CGSize screenSize = [UIScreen mainScreen].bounds.size;
CGFloat screenHeight = MAX(screenSize.width, screenSize.height);
CGFloat const IPHONE_4_SCREEN_HEIGHT = 480;
UIImage *image = [UIImage imageNamed:imageName];
if(screenHeight == IPHONE_4_SCREEN_HEIGHT) {
CGFloat const xScale = .85333333;//x conversion ratio from iPhone 6's 375 pts width screen to iPhone 4's 320 pts width screen
CGFloat const yScale = .71964018;//y conversion ratio from iPhone 6's 667 pts height screen to iPhone 4's 480 pts height screen
CGSize newSize = CGSizeMake(xScale * image.size.width, yScale * image.size.height);
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
[image drawInRect:(CGRect){0, 0, newSize}];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resizedImage;
}
return image;
}
Resizing a big image (iPhone 6) to a smaller one (iPhone 4) doesn't lose much quality even if the aspect ration is not the same.
Using an existing project when moving to Xcode 6 and iOS 8 creates some initial issues. I solved this by changing the image set from Device specific to Universal. This removes the R4 image option and leaves you with #1x, #2xand #3x. If you use for example a background image that needs to fit the screen then I will recommend that you find an image that does not have to fit 100 % perfect to look good, and set image to be displayed as Aspect Fill.
I have the same problem and got confirmation from apple that I have to wrote code for that. For example you can try like this Fullscreen images on iPhone 6 with Asset Catalogs
But I actually went lazy about it by using one 2x for 4" & 4.7" screen and another 2x for 3.5" screen

Retina image displayed too big in retina simulator

I display a retina image (with #2x.png extension) using:
myImage = [UIImage imageNamed:#"iPhoneBackground#2x.jpg"];
UIGraphicsBeginImageContext(myImage.size);
[myImage drawAtPoint: CGPointZero];
myImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView = [[UIImageView alloc] initWithImage:myImage];
NSLog(#"Dimension:%f x %f",myImage.size.width,myImage.size.height);
[self.view addSubview:imageView];
However the image is displayed twice its size on the retina simulation. Image and simulator both have 640 x 960 resolution, so I would expect the image filling the screen.
I know there are other ways than CGContext to display an image, but that's the way I would need to other purposes in my code.
Any idea why I have this definition issue ?
Don't use #2x suffix
From apple documentation:
The UIImage class handles all of the work needed to load
high-resolution images into your app. When creating new image objects,
you use the same name to request both the standard and the
high-resolution versions of your image. For example, if you have two
image files, named Button.png and Button#2x.png, you would use the
following code to request your button image:
UIImage *anImage = [UIImage imageNamed:#"Button"];
You do not need to explicitly load a retina image, #2x will be automatically appended to the image name if the device has a retina display.
Change your UIImage code to: myImage = [UIImage imageNamed:#"iPhoneBackground.jpg"];

Should a universal app have 4 copies of each image?

In a universal app should I have a image.png, image#2x.png, image~ipad.png and image#2x~ipad.png for every image in my project?
Or should I just use my wider iPad images and have iOS scale them down to iPhone for me?
There's a lot of images so I'm a bit concerned about the file size...
Thanks!
Not necessarily but you can see code below. If you are targeting low res iPads and Low res iPhones you would have one set of icons for each. So if you are targeting iPad retina and iPhone retina that is on set of icons too so if you have an image called car.png and car#2x.png you would have 2 icons that cover all 4 models mentioned.
You can of course have images specific for iPad as the screen is larger then in your logic you would show either or depending on the device idiom..like below
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
//Device is iPhone
//This would give you low res icon for iPhone and if device is retina system will show it
UIImage *car = [UIImage imageNamed: #"Car.png"];
UIImageView *carImage = [[UIImageView alloc]initWithImage:car];
}
else {
//Device is iPad
//This would give you low res icon for iPad and if device is retina system will show it
UIImage *carLarge = [UIImage imageNamed: #"CarLarge.png"];
UIImageView *carImage = [[UIImageView alloc]initWithImage:carLarge];
}

Xcode 4.5 background image iPhone 4, 4s, 5

I have in my viewController.m written the background code:
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"image.png"]];
And I have the correct names of the different pictures:
image.png for non-retina display (320x480)
image#2x.png for retina display (640x960)
image-568h#2x.png for iPhone 5 (640x1136)
But when I run it in the simulator it does not take the image-568h#2x.png for iPhone 5 screen it only takes the image#2x for 4s screen and scale it to fit the screen... I dont know if there is any coding to use the image-568h#2x for iPhone 5 screen?
Im using Xcode 4.5
iPhone 5 is retina, just like iPhone 4 and 4S, and the #2x-image will be used automatically for all these devices. It's only the startup-image that is called "-568h#2x" for iPhone 5. You need to write some code to use a different image, something like this would work:
NSString *filename = #"image.png";
CGRect screenRect = [[UIScreen mainScreen] bounds];
if (screenRect.size.height == 568.0f)
filename = [filename stringByReplacingOccurrencesOfString:#".png" withString:#"-568h.png"];
imageView.image = [UIImage imageNamed:filename];
if you are trying to use [UIImage imageNamed:#"image.png"] and expect image-568h#2x.png to be picked automatically from the bundle for iPhone 5, it will not work.
Automatic picking works only for iPhone 4 and 4S.
Only the Default image named as Default-568h#2x.png will be picked automatically in iPhone 5.
for normal images, if you have separate image for iPhone 5, try using this code
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568) {
// code for 4-inch screen
} else {
// code for 3.5-inch screen
}
I believe it is incorrect to assume that you can apply the -568h#2x trick to all image files. I think it only works for Default-568h#2x.png. This is the file that iOS looks for at app launch on a 4" display device, as well as the "flag" to enable 4" display support in the SDK. For example, once you include this specific file, your table views will fill the screen.
I have not read anything to suggest that you can simply provide any image with the -568h#2x file name component and have it be used automagically. You'll have to do that yourself based on the screen size, e.g. [UIScreen mainScreen].bounds.size.height.

Resources