I am in the process of learning iOS development with XCode. I created a project to implement some of the things I've been learning and to begin learning how to manage image sizes and placement on different sized screens i.e. iPhone 8, iPhone 8+, iPad, etc. I am currently using XCode 10 Beta and I noticed that the View size on the main storyboard is half the actual screen size of any device I select to to View As:. For instance if I select View As: iPhone 8 the screen size is 375x667 instead of being 750x1334 like the actual device. I discovered this because I created a square image of 100x100px and thought I would be able to line up 7 across the screen. To my surprise the images took up twice as much screen as I had calculated.
Can anyone let me know why the screen Views in XCode are half that of actual screen size?
Do I just always assume to make my graphics half the size I would actually want them?
Edit: Here's a screenshot of what I am referring to in XCode
When I click on the empty view in the the XCode storyboard pane this is this resolution it displays for the view. Also, when I export my graphics from Illustrator the are exported with the #1x, #2x, and #3x variants. However, when I place an image in the view that is 100x100px it takes up about 1/3 of the screen instead of 1/7 of the screen as I would expect on a iPhone 8 which has a resolution of 750x1334.
Edit #2: So after playing around more with XCode I do see that the resolution for the views are in Points not pixels however, in this screenshot for a iPhone 8+ View:
I would assume with a screen resolution of 1080x1920 #3x the Point resolution would be 360x640 for an iPhone 8+ not 414x736.
It has to do with the difference between points and pixels. On the original iPhone when it was release it was 1 point per pixel but as resolution got better it became 2x pixels per point (4 pixels). Now the resolution is 3x pixels per point on some of the newer devices (9 pixels).
https://www.google.com/amp/s/blog.fluidui.com/designing-for-mobile-101-pixels-points-and-resolutions/amp/
Related
I have an application for medical calculations and analysis that utilizes dozens of screens for data entry, each with carefully spaced entry and display fields. The app has two versions of each input screen, one for pre-iPhone X screen dimension (640x1136 ratio), and one for iPhone X screen dimension (1125x2436 ratio). In the LaunchImage section of the current Assets.xcassets scheme for launch screen images, I have a black png image that is 640x1136 pixels entered into the Retina 4, Retina HD 5.5", and Retina HD 4.7" slots, and a 1125x2436 pixel image image entered into the iPhone X / iPhone Xs slot. By placing images in this way, the OS automatically preserves the needed screen layouts, regardless of the size of the iPhone screen, even though I have a compiler warning that two of the launch screen images are the wrong size.
With the upcoming requirement to use a launch screen storyboard, I am unable to find, after extensive research, any way to preserve the crucial functionality that I have had to date, using the size of the launch screen image to enforce formatting dimensions. I understand the intent of the launch screen storyboard to simplify support for multiple devices with different screen shapes and sizes, but in my particular case, the new requirement introduces a very significant problem. Am I missing something, or is there a way to use the new launch screen storyboard in the manner that I have been using launch images?
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+.
So I am creating a Sprite Kit game and I want to have the same look on every device(no iPad, for now), as if it was the same scaled image.
So far I have my background images figured, 4 images for every screen size, chosen at runtime by checking the height of the screen. All my other images are designed for iPhone 6 plus, so I have #3x and #2x(66.6% of the #3x original image), that means I have iPhone 6 plus and iPhone 6 pixel perfect images.
The problem: Ran on iPhone 5/5s or 4/4s the images don't change size, they are as big as on iPhone 6, which is normal, they use the #2x. I want the images to scale by screen size. I know I have 2 options: use 4 sizes for every single image or scale the images by "screen height" / 667(iPhone 6). Both solutions are not good, because the first makes the app bigger and the second involves checking if it is iPhone 6 plus(use the #3x) and then scaling every single image, also both add a lot of code, I strive for clean code.
The first solution is acceptable, only if there is no other. Sorry for the long explanation, just want you to know what's going on.
We want to support iOS 6 through iOS 8. By my count, that means we need to create ten launch images.
portrait 2x3: 320x480 640x480
portrait 9x16: 640x1136 750x1334 1242x2208
portrait 3x4: 768x1024 1536x2048
landscape 16x9: 2208x1242
landscape 4x3: 1024x768 2048x1536
What I wish is that I could just generate the largest sized image at each ratio, and that iOS would just downsample the image for the other sizes. That would save me from adding five more launch images to my app, a nice savings in download size.
Is it possible to use the new feature of Xcode 6 to replace my launch images with storyboards (aka UILaunchStoryboardName) to do what I want?
It seems pretty close, but I can't figure out how to say, "At 2x3, use image X; at 9x16, use image Y; at 3x4, use image Z" and so on. Size classes don't seem to let me express that concept cleanly. (Or do they?)
Here is one way to do this... Create a new image set in your existing or some new assets catalog. By default, the Devices field of the new image set, in the right pane, will be set to Universal, and so you should see three image wells in the main view: 1x, 2x, and 3x. What you want is to set the Devices field to Device Specific, then check iPhone, Retina 4-inch, and iPad underneath that field. Then, you will now see six images wells. There are four for iPhone: 1x, 2x, Retina 4 2x, and 3x. There are two for iPad: 1x, and 2x. Now, all you have to do is to drag your versions of the same splash image in various device-specific sizes, into the appropriate image wells. Once you are done, go to your launch screen XIB, which by default is set to Any width and Any height, and add a UIImageView, setting the image to have the same name as the image set you just created. Adjust the image to have the same size as the enclosing view, adding top, leading, bottom, and trailing constraints with a constant value of 0, so that the image size adjusts with the view size, regardless of the device. Run the app on your device and you should see the correct splash upon launch. You can set a breakpoint at the top of your AppDelegate code, e.g. right underneath the var window: UIWindow? declaration (or equivalent if using Objective C), so you can verify the splash on different kinds of device. Note that the image may not work in the Simulator, so try on a device. I guess that it is a bug in the Simulator, or unimplemented feature.
One thing I am not sure about is where to specify the image for iPhone 6. It seems that there are device specific image wells only for iPhone pre-4s, iPhone 4s, iPhone 5, iPhone 6 Plus, iPad, and iPad Retina sizes.
I've searched a lot but find nothing about frame and dimension. I thought this should be a big topic.
Anyway, when create a view using frame, the whole screen size is 320*460 (320*480), but the dimensions of screen is 720*960. Can someone explain this? How to convert them.
This is only for 3.5 inch non-retina device.
EDIT:
I figured it out. The problem is because the size of iPad and iPhone is different. For iPhone, the dimension is 4:3, but for iPad, the dimension is 1.33.
Check out:
http://www.idev101.com/code/User_Interface/sizes.html
Points are how the screen is measured by apps so if you place something at a position you place it at a point. There are two pixels per point on retina devices.
This is only for 3.5 inch non-retina device.
No, this is the point. 3.5 inch retina devices have a resolution of 640*960.
For development Apple convert this resolution to the old 320*480 dimensions. Why ? To develop the same way for retina and non-retina devices. Except that you have to provide retina image. For a classic 100x100 image named myImage.png you have to provide a 200x200 image named myImage#2x.png. But all the development except that is the same. There are 4 times more pixels per point (ppp) on retina devices than on old iOS devices but it's transparent for the developers.
For the 320*480 vs 320*460 point : this is the status bar. In iOS < 7.0 status bar took 20 pixels height. You always should trust the [UIScreen mainScreen].applicationFrame.size to get the application size within the phone.
Update : you talk about uiimagepickercontroller don't mistake pictures taken from the camera (or from the web) with the screen resolution !