Some background: the first release of our music practice app Soundproof was “Waiting for Review” in the last week of September when my iPhone 6 arrived. I ran the app on the iPhone 6 and of course got the stretched up iPhone 5 UI. It was OK, but a bit “Duplo” shall we say. Also our very subtle background gradient was being stretched. Nobody else would notice but… there is pride to consider.
We already had oversized controls on the iPhone 5 as part of our intended usability features, and this was making it ridiculous because everything was being scaled up. We needed to selectively increase the size of UI elements to use the new screen real estate… but how would we achieve this?
Xcode 6 and iOS 8 introduced support for new @3x assets to handle the iPhone 6 Plus. This means assets are supported in Xcode for 1x, 2x, R4 and 3x sizes. For those who weren’t paying attention the R4 asset was introduced with iPhone 5 to allow different graphics for the taller display — think full screen background images that you don’t want stretched to fit the different aspect ratios of iPhone 4S and iPhone 5.
The problem is that iPhone 6 uses R4 or 2x assets, depending on which you have defined, and iPhone 6 Plus uses 3x. The same assets that the iPhone 5 family uses.
In particular, this affects our play/pause button. The rest of our UI is very minimal, and what you find is that if you add native iPhone 6 support, using the same assets as iPhone 5/5S/5C the large buttons are too small in proportion to the screen size and the visual balance is lost.
The tiny 2x play button makes our app look stupid on iPhone 6. We already had to have a specific size for iPhone 4/4S due to the restricted height on that display, so 2x and R4 were already different. We aren’t about to add a bunch of unnecessary UI on screen just to fill the gaps on iPhone 6, so we had to restore balance.
We could have simply adjusted the constraints and had the iPhone 5 images stretch — but that would be horrible. However, Apple decided not to add an “R4.7” asset size to enable different resources for iPhone 6. I can see why having support for specific assets for every display size they make is not something most Apps need — many Apps are just about displaying content, not creating a tactile pseudo-mechanical user interface. It is interesting how Apps for musicians, while not necessarily requiring skeuomorphic design, tend to require this kind of interface. Camera Apps also fall into this category.
You may be thinking “but PDF assets would just handle this for you”. In this case PDF assets do not help. They are simply rendered to images at an appropriate size multiple — there is still no asset “slot” that will be used only for iPhone 6. For example a 1x PDF will be rendered the same proportional size for 2x, R4 and “R4.7” (iPhone 6) and 3x devices. This is not what we want for the play button or background images.
This is what we needed to achieve:
For now we came upon a relatively simple solution. With assets that we want to vary in size on each device screen size contrary to the proportions of the UI as whole, we treat these as “oversize” and handle them separately.
(notice that we do not actually have 1x resources, we have not bothered as we don’t support any 1x devices apart from running scaled up on first generation iPad mini)
- a single image set for 1x, 2x and R4. This covers iPhone 4, 4S and 5/5S/5C – as well as iPads scaling the app up from iPhone 4 layout
- an “xxxxx-oversize” image set for iPhone 6
- an “xxxxx-overize@3x” set for iPhone 6 Plus
We can use PDFs or PNGs in the appropriate slot in those discrete image sets as long as the 2x in “xxxxx-oversize” will result in the larger size we want, and the 3x in “xxxxx-oversize@3x” produces the correct size for iPhone 6 Plus.
We have a custom category on UIImage to load from the correct asset based on display size. This is very dumb right now, and does not fall back to the “standard” image set if there is no oversize variant defined. Also, sadly this means these images cannot be assigned in Interface Builder and require code to set up.
Granted, this is far from perfect. We’re effectively duplicating some of the image asset functionality, and we’re making assumptions based on display sizes that almost certainly will not hold in future… but as a quick fix until there is more information and experience available it works well enough. We might have to swap this out for device-specific image selection which is ugly but better than screen size calculations.
Why did we split out -oversize@3x instead of using the 3x slot in the normal image set? We need to be able to have a button that is a custom size as well as being 3x to maintain the visual balance on iPhone 6 Plus otherwise the screen feels empty with the normal play button @3x. Our 2x play button is 164 high, the R4 is 204 high, and the 3x is 404 high. There’s no way those calculations work with standard multiples.
It will be interesting so see what happens as the screen sizes diversify further. I think this will always be tricky for these kinds of user interfaces — there is no silver bullet. The worst problem is how future unknown devices are handled when you add device-specific code like this. In addition, our use of 3x and this nebulous “oversize” concept will likely come back to bite us when apple releases another 3x device with a different screen size.