I have a question about using images for universal apps on IOS.
I've created a universal app that works on all iphone devices and ipads. I've placed all the content via storyboard. On a View I have two buttons one on the top space area that is 40 points high and as wide as the view, one on the bottom area also 40 points high and as wide as the view and an image that is a square (A x A) in the middle of the view, the image is constrained by horizontal and vertical (For it to stay always aligned in the middle of the view).
(I understand that if I use an image that is 100 points by 100 points image at 1x, I need to create two other images at 200 points by 200 points for 2x and 300 by 300 for 3x.)
1) So if I constrain the UIImage container by height and width equal to 100 by 100, it will be 100 by 100 points in all devices. But I want it to use as much space as possible. That would mean that on iphone 5 - 6s+ it would always be 100 by 100, it would look smaller on every growing screen. It would also mean that I would need to make it bigger for Ipad (Storyboard changing to regular regular to change UIImage container size for ipad, ex. increase it to 300 x 300). Put once I make it bigger, the image I have will be to small for that size therefore turn blurry or pixelated.
Right?
2) If I would like to be able to use as much space as possible I thought of using the following method. Constraining the UIImage to be equal width as the view but reducing its multiplier to 0.9 or 0.8 (Therefore making it smaller then the view width) and placing an aspect ratio of 1:1(To maintain it square). That way taking advantage of most of the view space that is free, and In all the devices it would always seem filling the same space. However the problem would be that the image would have to be different sizes. (Ex. iphone 5 = 150 x 150, on iphone 6 = 250 x 250, on iphone 6+ = 320 x 320 ans on ipad 600 x 600).
so If I make an image that in 2x that is 150 x 150, when its used on the iphone 6 it would be distorted or pixelated and the same for for the rest.
So can someone help me understand what I should do? or link a tutorial?
Please help!!
I've found that the best way to solve this problem would be to make a much larger image and let the constraints resize it. That way, you've covered your bases if new resolutions are developed, or with the current varying sizes. A much larger image would not look bad if it was compressed into a smaller space, but you might lose some details.
Related
I'm making a spritekit game. I understand how to size my images in an SKScene because it's 750x1334 points across all devices, but the main page of the app uses UIKit/a collection view controller, so I'm not sure how to size my images. I want to have the images take up 1/3 of the screen width and then have the image height equal the image width.
iPhone SE is 320x568 points
iPhone 7 is 375x667 points
iPad Pro 10.5 inch is 1112x834 points
Do I just make images that are 1/3 of the largest possible device width (1112 points) and then let smaller devices scale the images down? i.e. 1112 points divided by 3 is 370 points, so make images that are 370 points wide and high (740.6px#2x and 1112px#3x)?
I want to have the images take up 1/3 of the screen width and then have the image height equal the image width. Do I just make images that are 1/3 of the largest possible device width (1112 points) and then let smaller devices scale the images down?
No. When you "let smaller devices scale the images down", you are still loading the full-sized image and thus wasting memory. Plus, letting the runtime scale the image down automatically (e.g. because you use an image view with an aspect fit or aspect fill content mode) wastes time and processing power, often at a critical moment when the app is trying to launch.
The correct procedure is:
In your app bundle, you should include just one size for the image, possibly in three resolutions, and this should be the smallest size that is acceptable on the largest screen you'll be showing on.
In your code, you should figure out the size at which the image will actually be displayed for the screen of the device we are running on, and load a thumbnail of the image sized down to that size.
In this way, no memory is wasted; the image held in memory is the image as displayed.
In Storyboard, you can use the below steps,
Put equal width and equal height between image view and your actual view
Select the equal width constraint and change the multiplier from 1 to 1:3
Select the equal height constraint and change the multiplier from 1 to 1:3
The image view should occupy 1:3 of your screen size now.
Screenshots are attached for iPhone and iPad designs,
Hope it helps.
I spent hours of searching about this topic, but nothing is exactly dealing with my problem. Maybe you guys can help me better.
I want to ask what is the proper way of designing a layout to properly support all the iPhones. Also the easiest way for me as possible.
My style is that I am designing for the smallest device first and then scale things up for the other devices. Is that alright or is this not how it is supposed to be done?
My problem is that I am creating a layout that should scale up according to display size.
I will give an example of Original iPhone which has screen of 320 x 480 points (which equals 320 x 480 pixels) and iPhone 6, which has screen of 375 x 667 points (which is 750 x 1334 pixels because of the different pixel density).
Now I want to make a button or textbox or rectangle (whatever) on the Original iPhone that will get bigger if I launch it on bigger device like iPhone 6.
So if I have a button having height of 30 (pt) on Original iPhone, it should be bigger on iPhone 6. But how much bigger?
Do I have to calculate those 30 pt into pt on bigger device myself every time, or is there better method that works automatically so I don't have to re-count all the dimensions for every device? What is the correct way?
Btw: I am aware of that when designing the icons, buttons, or anything that is a .png file, I have to create them in dimensions of 1x, 2x and 3x so it can scale on all the devices, but how to work with these while constructing the actual layout?
What is the logic or how is it ment to be done?
THIS PICTURE is showing the dimension proportions I found on the web and little bit of idea of my problem below.
EDIT: Please look at this website: https://designcode.io/iosdesign-guidelines
It seems like there are some Apple's measurement standarts in (pt).
For example on one of the pictures they are showing that the margin from the sides should be 8pt. Since [pt] is an universal unit, I would expect it to adapt on other devices. So if I set the margin of 8 in editor, will it make different ammount of pixels on the other devices so it looks visually the same?
If you calculate every view like this one , it will not work.
Just set constrains on that view which you want same in other devices.
Like if you fix a view's height is 30 then it will 30 in every device. It is not going to be bigger or smaller in other devices.
But if you think that, a view is 20 pixel from right and 20 pixel from left, 10 pixel from top bar and bottom layout then this view gonna same ratio in every device.
I hope you understand what i want too say.
Please comment if i am unable to make you understand. :)
I am creating an Ipad app and no matter what height I set my ImageView to be it is always too big.
For example I have an ImageView that's about 20 pixels tall and has all of the constraints that I need to keep it where I want it to be. When I play this 20 pixel tall ImageView on the Ipad simulator the ImageView covers about half of the Ipad screen.
How can I work with Ipad images if even a 1x1 pixel image view takes up a signifiant amount of the screen? (Yes, I made the 1x1 image just to see if it would still be insanely large)
Under Auto Layout, if you don't set the size of the image view absolutely, it will size itself to match the size of the image assigned to it. That is probably what is happening to you.
The apple guides haven't helped me too much with this but I am starting to get serious about IOS development and was taken aback when I saw images go from #1x to #3x.
One source I found said they were based on sizes. For example:
If you are working on an inferred VC size and your image is 30x30 and you run that on a iPhone6 then your image should be 30x30 for #3x, 20x20 for #2x, and 10x10 for #1x.
Another source I said mentioned that it was based off the images resolution and not the size of the image.
Could someone clear this up for me and explain how to make sure my images look professional for all screens?
Thanks in advance!
When the first iPhone (and SDK) came out, all images were 1x (1 pixel of the image = 1 pixel of the screen), because that's all we had to care about. On that phone there were 166 horizontal or vertical pixels per inch (dpi). So to display an image that stretched from the left edge to the right edge, our image would need to be 320 wide (because that's what Apple told us - we didn't have to count pixels) by whatever height we wanted. Let's say 100 pixels tall. We'd name that image MyPhoto.png (because Apple told us the iPhone OS worked best with PNG images) and we'd display it.
When the iPhone 4 came out with the retina display, its retina display had 2 times the horizontal and 2 times the vertical resolution of the older phones. So now we needed higher resolution images to get the best looking interface. We were still displaying just a 2" wide image, but it would need twice the number of horizontal pixels and twice the number of vertical pixels (4 times the total number of pixels) to fill the same space. So now our image needs to be 640 pixels by 200 pixels. Since our app would still need to support the older phones as well as the new phones, we didn't want to just replace the old image with the new one. We needed a way to support both. So the old images kept the same name they had before (we didn't append "#1x") and the new images got the "#2x" filename extension to indicate they were twice the resolution. So we'd name this larger image MyPhoto#2x.png.
A common question is why not use just the higher resolution images on both old and new phones? With scaling, both appear to work great. The problem primarily is that the iPhone, especially the older phones, had very limited memory to work with. Using images that are 4 times larger than they need to be is really hard on that limited memory. That's why we had to have both 1x and 2x images in our apps.
For our sanity, we would still just use 1x while designing the interfaces. So screens remained 320 pixels wide in our code, even if we were going to display them on a retina display that was 640 pixels wide. If we wanted to draw a 1 pixel wide line on the retinal display, we'd make it half a pixel wide in our code.
With the larger screen of the iPhone 6 Plus, Apple had to pack even more pixels on the screen to maintain the high resolution customers came to expect. So now we're into 3x images. However, the iPhone 6 Plus doesn't really have three times the number of horizontal or vertical pixels. But again Apple has kept us sane by just asking us to supply "#3x" images, and it worries about scaling them down a bit on the device. As before, we still need to support smaller screen resolutions too, so we still include "#2x" and the 1x images in our apps.
So, to continue our example, the #3x image would need to be three times the width and height of the 1x image. So now we need a 960 wide by 300 pixel tall image. We'd name it MyPhoto#3x.png.
Notice that although I mentioned earlier something about a 166 dpi display, that's not really important when creating these images. In your photo editing app you don't really care if the image is 166 or 72 dpi or anything else. The only important part is the number of pixels in width and height of the final image we export.
So to answer your question (hopefully), you'll want to include all three of these images in your iPhone compatible apps. You can skip the #3x image for iPad-only apps, because there's no 3x screen yet for the iPad. But continue to think only in the 1x size when working in Interface Builder and code.
For example, now to display a 1 pixel wide line on the iPhone 6 Plus, you'd draw a 0.33 wide line rather than a 1 point line. Of course, you still want to support all of the other screen resolutions too, so you'd use code like this to set your line width:
let lineWidth = 1.0 / UIScreen.mainScreen().scale
This will give you 1.0 for the non-retinal iPhones, 0.5 for the iPhone 4, 5 & 6, and 0.33 for the iPhone 6 Plus.
I have a simple view with a text and an Image. I ran this app on iPhone6Plus and iPhone5. Then I made a screenshot of both and enlarged the iPhone5 screenshot such that it matches the size of the screenshot from iPhone6Plus. Here is the result:
As you can se the size of the text the size of the image and there positions are not identical but they should be to look the same on different screen sized.
Here is an example of a weather app running on different screens:
As you can see the sizes and the positions of text and image are identical.
The image is loaded from asset catalog:
imageView.image = UIImage(named: "shower3")
self.view.addSubView(imageView)
imageView.center = self.view.center
I have only created a 128x128 image and put it into the #1x version in the asset cataloge.
Let me rephrase this. I run the wether app on iPhone5 make ascreenshot and iPhone6 make a screenshot. Then I resize both screenshots to the same size. Then I see that both fontsize as well as images dimension are exactly equal on both screenshots. This means that on each device font and image must have different dimensions. How can I do that?
How can I achieve that text and image have identical proportions on different screen sizes? How does the Weather App do it?
Images
I am the creator and one of the developers of the Swift Weather app. The app doesn't use three versions of images because I didn't make those images and it was a Pull Request from another developer. I don't have the origin images.
As #Daniil Korotin mentioned, iOS uses points to calculate image and font sizes. iOS uses let screenScale = UIScreen.mainScreen().scale to retrieve the screen scale and pick up the proper size (1x, 2x or 3x) of the image. If we don't provide the proper size of the image, for example, in SwiftWeather app, we have only 1x version of the image (as the screenshot below), iOS will upscale the image to render on retina devices. On iPhone 6 Plus, it actually does downsampling for 3x assets. Please have a look at iPhone 6 Screens Demystified. In some case, if you don't provide 2x or 3x images, on retina devices, the image upscaled from 1x may looks blurry. We should always provide 1x, 2x and 3x images if possible.
Fonts
iOS renders fonts according to the specified points. It will automatically convert the points to certain pixel based on the devices' screen scale (as mentioned above).
How can I achieve that text and image have identical proportions on different screen sizes? How does the Weather App do it?
The answer is Auto Layout
You can see we set constraints for the image view (used for the weather icon) as below.
The width and height are always 150 points, please notice it is points nor pixels. It will render the same size (for look and feel, not for exactly pixels) for different devices. For your first image (iPhone 6 Plus vs. iPhone 5), it looks different because maybe your simulators have different scale. A better way to check how auto layout elements lay on the screen is to use Preview in Interface Builder.
Open the main storyboard, and click on Assistant Editor. On the right hand side, select Preview (on the top left). And click the plus sign ( on the bottom left) to add different devices. You can see they are identical proportions on different screen sizes.
If you have any questions, please let me know.
Something maybe off topic
If I design the images/assets, I would like to use some vector base tool like Sketch to design the assets and export them to three different sizes. Please have a look my another project iOSAnimationSample. It has a Sketch file for the design.
Sketch design
Export assets to different sizes
In that case, iOS can pick up the proper assets for different devices.
The app you are referring to does not correctly support multiple screen sizes. The interface is scaled up to run on the 6 and 6 plus, which is why everything appears the same size.
Look at the screenshots from your app - the status bar is much smaller on the 6 plus. This is because it is supposed to take up less room on the screen. It's 20 points high on all devices.
Now look at the screenshot from the weather app - the status bars are the same size. Because the weather app does not support multiple screen sizes, iOS simply takes the smaller interface and scales it up to fill the screen.
If you want to achieve the same effect (which you shouldn't) then remove the LaunchScreen.xib file and use a launch image instead. But people don't buy larger phoned screens because they want to have the same content, but bigger. That would be achieved more cheaply by simply holding the phone closer to one's face.
You're supposed to take advantage of larger displays by allowing more content to be shown at once on the screen - more rows of data in a table, more text from a book, more images from a photo library.
In the case of a weather app the extra space should be used to display more rows of an hourly forecast or something, not just a larger version of a fairly useless icon depicting the type of weather.
I suspect it is only game support that means supporting larger screens properly is not already a requirement for app store submission. Supporting the 4 inch screen became mandatory quite quickly, you should expect a similar rule to be introduced for the 6 and 6 plus before too long.
If you want a specific element to always take up 50% of the width of the screen, or a label to always be the same size as an image, then you use autolayout constraints with multipliers. An autolayout constraint is of the basic structure:
attribute of A = (attribute of B * multiplier) + constant
Most of the time the multiplier is left as one, so you're just saying that this is 20 points to the left of that, or whatever, but you can use the multiplier as well, and say that A is the width of B, multiplied by 2 or 0.5 or whatever you like.
iOS uses points to calculate image and font sizes. On non-retina screen 1 point equals 1 pixel, on retina screens — 2 pixels, and for iPhone 6 Plus it is equal to 3 pixels (some downscaling is applied, though). If you want to scale the image and font based on the actual pixel size of the screen, you can get the number of pixel per point like this:
CGFloat screenScale = [[UIScreen mainScreen] scale];
The iPhone 5, 6 and 6 Plus screen aspect ratios are the same, while resolutions differ. If you want to simply keep proportions, then you have to pick a 'base' screen width or height (say, the iPhone 5 screen width, which is 320.0 points) and then calculate the proportion by dividing the actual device screen width (say, iPhone 6 Plus screen width, which is 414.0 points) by that 'base' width (414.0 / 320.0 = 1.29375). You can get the screen size like this:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
Dividing screenBounds's width by base width gives you the proportion. Then you just multiply all the sizes and margins with that proportion (1.29375 in our case for iPhone 6 Plus). Hope you get the idea.
P.S. A good guide to resolutions is here.
P.P.S. And in your case, as skorolkov mentioned below, the app just upscales everything for bigger screens (add/remove splash screens to enable/disable this upscaling).
UPD: Ok, now I see what confuses you. Here's the thing: when Apple initially released iPhone 6 and 6 Plus many apps didn't support their larger screens and bigger resolutions. So they decided that if an app lacks splash screens specifically made for those phones, it should use the iPhone 5 resolution.
That's why you get the exact same pictures after manually resizing screenshots: the system does that too. It simply takes iPhone 5 'picture' and stretches it so that it fits larger screens. The drawback is clear (and visible, especially on iPhone 6 Plus): the fonts and images are blurry and upscaled (system interface elements, like status bar, get upscaled too). So basically you get the iPhone 5 picture on all larger-screened devices (you can check that by taking a screenshot on an iPhone 5, resizing it manually to fit iPhone 6/6 Plus resolution and comparing the actual iPhone 6/6 Plus screenshot to it).
To be clear: that's the behavior you currently get, but it's not good. To keep everything properly scaled using the devices' native resolution, use the method I described above (manual multiplication) or autolayouts with equal height/width set to desired ratios for interface elements.
Weather App is using upscale mode to run on iPhone 6+. You can enable it by removing launch screens for 6/6+.
Go to asset catalog, select your launch image and unset 'iOS 8 or Later' checkbox in Attributes Inspector.
Screenshot - your app has this set
Screenshot from WeatherApp
in programatically (X and Y) we pre define the values in constant :
#define XScale [[UIScreen mainScreen] bounds].size.width / 320.0f
#define YScale [[UIScreen mainScreen] bounds].size.height / 568.0f
Then create UIImageView programatically
var imageView : UIImageView
imageView = UIImageView(frame:CGRectMake(XScale *someValue, YScale * someValue, XScale *someValue, YScale *someValue));
imageView.image = UIImage(named:"image.jpg")
self.view.addSubview(imageView)
based on your screen size we need to set Constant values. We use for iPhone5 and 4s screen.
You need to set Layout constraint to all the views to make them look at same places and sizes in all screens sizes provided that the aspect ratio of screens are same.
Have you tried to remove autoResizingfunctionality from view?
Click on inner arrow to remove autoResize view as per superview
First turn off auto layout, auto resizing and size classes in storyboard.
Click on Images.xcassets icon and select all your graphics. In attribute inspector set Devices property to "Device Specific" and set the checkbox checked against "iPhone" and "Retina 4-inch"
Place all your graphics in 2x image set. You may place a higher resolution image set for better results with iPhone 6/6+.
Design your view for a reference device say iPhone 5 (320x568 portrait).
In your viewDidLoad method paste the following code
self.view.transform=CGAffineTransformScale(CGAffineTransformIdentity,self.view.frame.size.width/320, self.view.frame.size.height/568);
And you will have same result on iPhone 5/5s, iPhone 6/6+.