I once read someone on Twitter say that “Type is the one constant across all screen sizes” — it’s true if you don’t include top, left, bottom and right.
Adapting an app to different screen sizes can be a challenge sometimes. But, with some basic techniques and tips, it can be easily achieved, with little code.
Firstly, let’s look at the problem — modern smartphones and tablets come in many different shapes and sizes. Traditionally this was a big problem on Android where devices with varying aspect-ratios, densities and physical resolutions meant you could be targeting thousands of devices from a single codebase.
In the last few years and with the advent of larger iPhones and iPads (and rumours of even more coming in 2018), we’ve seen this problem come to iOS too although (so far) it’s not been as bad as with Android.
Still, right now you could be developing an app that has to target a 4”, 4.7”, 5.5” and 5.8” screen for phones, and 9.7”, 10.5” and 12.7” for iPads, and all have different resolutions and density requirements.
There are a few things to consider when looking at supporting different screen sizes:
- form factor
- image resolutions
- UI differences
With form-factor, you have to consider if you’re targeting a handheld / phone or a tablet device. In each case, it may not be as simple as scaling up like a web site when they run on tablet devices, with more white space, and “wider” content.
Orientation changes are common on devices too. And, despite the fact you can fix an app to a specific orientation, it’s common for apps to work in both portrait and landscape, especially on tablets, meaning the orientation can change on-the-fly. Fixing particular elements in this case means the layout could look broken if the user switches to landscape in a portrait app.
Image resolution is a big one — mainly because Android requires different densities, and iOS has different retina resolutions, x1, x2 and with the iPhone Plus and X, x3.
When it comes to OS controls, there can be some key differences between handheld and tablet devices. For example on iOS, a Tab Group has its labels under the icons on iPhone but next to them on iPad.
For larger devices like the plus phones and iPads, you have a SplitWindow controller to show a list view and detail view at the same time. These can also appear only in landscape, reverting to just a list view in portrait mode.
Pickers are another area where the UI can change — on iPhone the typical way to do this is slide a view up from the bottom showing a date picker etc. On iPad, these usually appear as a popup window appearing next to the related control.
There are ways to mitigate the potential code changes you have to make to support these — writing a module, redefining Alloy tags can allow you to define a single XML view that will work on iPad and iPhone displaying pickers and list / detail views based on the device / orientation. You write the module once, test it and can reuse it in all your projects easily.
With all this in mind, there’s a few key things you can do to take advantage of and support different screen sizes and resolutions:
- Center controls by specifying width — by just setting a width, height and top / bottom value (and omitting left and right) a button or element will always be centralised on the screen — appearing the same on all devices.
- Anchor elements with top, right, bottom left — this is one of the simplest ways to create controls and layouts that work well on multiple screen sizes. By positioning elements based on known anchor points and using other techniques for size, width, and height, you can create a consistent experience across devices.
- Use Alloy TSS overrides — in Alloy it’s really easy to setup a base class/definition for an element, and then adapt this for various platforms or form factors using conditional TSS statements. You can even create your own methods e.g.
Alloy.Globals.isIPhoneX()and have this specified in a particular class or style to change the appearance of an element for a specific device.
- Create spacer elements or percentages — when dealing with taller phones / screens, you can help space out elements by either using percentage values to specify spacing vertically, or use custom views as spacers and adapting their height using conditional TSS-based on the screen height. This is really useful to limit the white space that can occur if all your content is bunched up at the top of the screen.
- Capture orientation changes and adapt views — it’s possible to add a listener for the orientation event and adapt your view accordingly — here are some examples of widgets and code that can do this for you allowing you to specify portrait and landscape TSS properties.
- Use tablet specific views and components — on tablets, and even on larger phones like the Plus and X, you can take advantage of components like SplitView on iOS, or a custom component on Android to give the user more content and features on a larger screen device. So, if you have a list-based application, you could design it in such a way that uses the list view on small screens, but on larger, horizontal layouts and tablets, uses a SplitView to show the list and detail views at the same time.
- Write modules or replace Alloy tags — there are some useful blog posts on redefining Alloy tags for cross-platform support, and this can be applied to screen size / cross-device support too. For example, I’ve written a picker control (which I’ll release soon) that allows me to define a picker once in the XML and it’ll automatically appears as either a slide-up picker on iPhones, or a popover picker on iPads. You could also write modules that can test screen sizes to determine the device type – like checking the resolution of the iPhone X and then having an
Alloy.Globals.isPhoneXproperty that can return true and be used as a custom TSS condition.
How do you handle supporting different devices in Titanium? Any tips, favourite modules, widgets or libraries — or any sample code you have that can help developers?
We’d love to hear your thoughts in the comments.