Mobile phones and tablets come in all shapes and sizes. This week we’ll look at how to prepare your app with images that match different screen densities. In a following posts, we will go through screen size specific images and resizable images. The more your images match a device’s screen, the better they look.
This blog post comes with an example app that we will be expanding in the next posts on images. It demonstrates all we’ll go through in this post.
Screen density or DPI
Two screens of identical size can have different densities. This is known as DPI, which stands for Dots Per Inch. Devices can have any DPI, but both iOS and Android have defined generalized density categories.
|~120||0.75||ldpi / low|
|~160||1||Default||mdpi / medium|
|~240||1.5||hdpi / high|
More abbreviations: D(I)P and LDF
In your app you will want to use the default D(I)P or Density-independent Pixel to set the exact size of all your views, be it
ImageView or other. This basically means you layout for 160dpi, and let the operating system scale up/down based on the LDF or Logical Density Factor, which is
DPI / 160.
NOTE: If you don’t set a
height on your
ImageView, it will display the actual size, which won’t be consistent across devices that don’t exactly match a generalized category.
Getting the screen density
In Titanium you can get all this information about the device via:
Providing density specific images on iOS
iOS uses filename suffixes to differentiate between images for specific density categories. Use
/images/image.png in an
ImageView and Titanium will consider the following paths, given the device falls in that or a higher category.
||HD Retina||iPhone 6 Plus|
||Retina||iPhone >= 5
iPad >= 3
iPad Mini >= 2
Providing density specific images on Android
Android uses folder names with so-called configuration qualifier names. As you can read in the Android API Guides there are many qualifiers, ranging from screen and input features to even day/night time.
You could have a folder as complex as:
In reality, you will just use a few. We’ll be looking at some of them in later posts, but when it comes to selection based on density categories you will use:
Android will use the image in the closest matching category. This might also mean it will use a higher category image instead of only falling back to a lower category. The last fallback is always
/images/res-mdpi/image.png and ultimately
NOTE: Another difference with iOS is that if you don’t set the size of your
ImageView and no perfect match is found for the device DPI, then the image will not show in the size you might expect. This is why you should always set at least one of
height. See the example app for a demo.
Because Android uses folder names, it handles subfolders in the
images folder a bit different from iOS:
Using remote images
Only on iOS can you also use remote density specific images. You do have to build the URL to the right image yourself using
Ti.Platform.displayCaps.logicalDensityFactor and set the
hires property of the
@3x images are not yet supported (TIMOB-18769). Use
Sharing (only) default images between platforms
One of Titanium’s great features is cross-platform support from a single codebase. However, you will want to keep the packaged apps as small as you can. For both images and other resources, you can use platform-specific folders. When Titanium packages your app it will leave out folders named after other platforms and move the resources in the target platform’s folders one level up.
Your assets folder
/images/android/android-only.png /images/iphone/ios-only.png /images/both.png
Result when packaged for iOS
Best practice folder structure
Since default images on iOS have no suffix the above leads to the following best practice to organize your image assets. For Alloy these paths would sit under
/app/assets and for classic under
As you see iOS and Android share the same default (160dpi) image. The images for xhdpi and xxhdpi can be copies of the (HD) Retina image, but then without the suffix. You can also safely ignore ldpi and xxxhdpi and save some bits there.
For additional information about how this works, make sure you check out this AppU Video.
For Android image paths have to begin with
/. This is not required but also doesn’t hurt on iOS, so please do.