Customizing Flex applicationDPI for a multiple screen size application
Building a Flex mobile application that works across smartphones and tablets takes an understanding of screen sizes, screen dots per inch (DPI) and screen resolutions. In the current landscape of devices typically you consider a tablet something bigger then a 5-6 inch physical screen. Also in the current device landscape screen resolutions are for tablets are typically greater then 1024×600 (original Galaxy Tab 7′ and PlayBook), while smartphones are typically less 1024×600. This of course will change as screens get better and have high resolutions.
How Flex works with helping you develop and design for multiple screens is provide a concept of applicationDPI
. This applicationDPI
is baked into the spark mobile skins, available in css media queries, and available to you any where in your code. Flex also provides a mechanism to override the applicationDPI
for your needs, I will get to this in a bit. First for an example of an application making heavy use of the applicationDPI
check out Caltrain Times. It is currently running across Android, iOS, and BlackBerry Tablet OS (PlayBook).
I have also personally tested it across these devices:
Device Name | Screen Size | Screen Resolution | DPI |
---|---|---|---|
Motorola Atrix | 4 | 540 x 960 | 275 |
Google Nexus 1 | 3.7 | 480 x 800 | 254 |
iPhone 3GS | 3.5 | 320 x 480 | 163 |
iPod Retina Display | 3.5 | 640 x 960 | 326 |
iPad | 9.7 | 1024 x 768 | 132 |
PlayBook | 7 | 1024 x 600 | 168 |
Galaxy Tab 7′ | 7 | 1024 x 600 | 168 |
Motorola Xoom | 10.1 | 1280 x 800 | 150 |
Nook Color | 7 | 1024 x 600 | 168 |
What is Flex’s Application DPI really?
Lets start with what its not. Its not a reflection of what the device’s actual DPI, for example the DPI values in the above chart. What Flex does for developers is provide 3 classifications you build your application against. They values are 160, 240, and 320, but you can think of them as small, medium, and large. Its also important to think of the Flex three DPI classification approach as your way to define what your application looks like and how it acts not relative it directly to device DPI. I explain two examples of why this is important with my Caltrain Times application. First is how to handle incorrect DPI values from the OS level. Second is applying your look to a set of devices by customizing the DPI classification in Flex. I’ll get to the detail of those two examples later in the article, first lets explain application DPI.
The definition, Flex’s applicationDPI
takes on two meanings. If you explicitly set the value your are telling Flex that this application is skin to applicationDPI=XXX
(160,240, or 320) and for the application to automatically scale the SWF and contents to the ratio of XXX/runtimeDPI
. The applicationDPI
classification strings can be found in mx.core.DPIClassification
. For more control of how your application looks for the different DPI’s do not set this value. Then the value of applicationDPI
is just a classification of 160, 240, or 320 (or some arbitrary value if you wanted to your own classification). By default Flex considers any device DPI of < 200 = 160, > 200 = 240 = < 280, and > 280 = 320. Now you can override the class mx.core.RuntimeDPIProvider
, in the first case this controls the scaling, the second case it sets the applicationDPI
value.
The rest of the post will make use of extending mx.core.RuntimeDPIProvider
to handle incorrect DPIs from the OS and control the look between phones and tables.
Handling Incorrect DPIs
It just happens that on the Android devices depending on the OS and manufacturers there is a chance of the device reporting their DPI incorrectly. I address this problem in Caltrain Times application, specifically on the Motorola Atrix, in my custom extended mx.core.RuntimeDPIProvider
class. The basis of my thoughts go back to the current landscape screen resolution and screen size values. I check the resolution threshold of 1024×600=614400 and screen size to figure out case that just don’t make sense. Here is the code for screenSize and pixel checking:
var screenY:Number = Capabilities.screenResolutionY;
var pixelCheck:Number = screenX * screenY;
var pixels:Number = (screenX*screenX) + (screenY*screenY);
var screenSize:Number = Math.sqrt(pixels)/Capabilities.screenDPI;
In the case of a high resolution 4 inch Android device with incorrect DPI of < 220 you'll find that the screenSize is getting larger then 5 inches. In my application I just looked for any device that was larger then 4.3 screen size (might have to change that as phones get larger displays) and its screen resolution < 610000 with a report DPI of < 220. If all those criteria are found I force it to return a value of 240 which the correct value I want.
Here is the code (with some checks for the my desktop case in there too):
Capabilities.screenDPI < 240 && pixelCheck != 1296000)
{
//trace("Force 240");
return DPIClassification.DPI_240;
}
Note: The source code can be found at https://github.com/renaun/CaltrainTimes/blob/master/src/com/renaun/mobile/dpi/CustomDPIProvider.as.
Applying your look to a set of devices by customizing the DPI classification in Flex
In this example I use similar calculations to figure out if the device is of a tablet size. The reasoning for my Caltrain Times application is that I wanted to overrider the typical DPI classification of 160 for tablets to be rendered at the DPI classification of 240. For my application with the larger look on the bigger tablet screens it feels the screen out nicely and works well. Again I go into the custom runtime DPI class to do this. Here is the code:
{
//trace("Force 240 Tablet");
return DPIClassification.DPI_240;
}
The “pixelCheck < 1920000 && pixelCheck != 1296000
" part is to handle running it through adl on my desktop. The rest probably makes sense, in the current device landscape tablets are typically larger then 7 inches and smaller then 11 inches with a resolution greater then 1024x600. If these values show up then I apply the DPI classification of 240.
Summary
The main take away is don't take the devices DPI at face value. If you want more control of your application across various devices make use of some classification constraints and check screen size, resolution, and DPI. It might seem like a bunch of work but this class can be used across applications and projects with minor tweaks depending on content requirements. Its also a good way to figure out if its a tablet or smartphone and outside of Flex DPI classification. Enjoy.
Check out my MAX 2011 talk where I go through Caltrain Times in more detail, as well as the source code available on github.com/renaun/CaltrainTimes.
Pingback: Cool Stuff with the Flash Platform - 10/24/2011 | Remote Synthesis