One of the great things about Android is the flexibility in the way it handles layouts. On similar phones with different pixel-resolutions, you can make the layouts stay proportionally consistent. This gives device makers freedom to work out the perfect screen and consumers broad choice among the flavors.
But what you as a developer might have realized, defining layouts to fit ALL devices is more complicated than that. When you make your app by following good layout practice, and happily test it on your normal phone (Nexus S for example), everything might look right. But when you try it out on a tablet (like the Galaxy Tab) or a small screen device (like the X10 mini), the layout might be cut off in some places or scaled wrong. This is because the densities of tablets and small devices fall into different "density-buckets". There's four of these density buckets: small, normal, large and xlarge. And your layouts will likely need to be adjusted to fit them all.
So without further ado, I have made a tool to do just that. The tool will scale your layouts to look proportionally good on tablets, small screen devices and everything in between. All you have to do is use density independent pixels (dp units) in your layout files, define your base-line density and define your new target density. Also... click a button.
The tool
I've called the tool ALASCA - The Android Layout Scaler. It's a simple java application with a graphical user interface. Choose your multiple xml layout files through the FileChooser, define your base width and height (the dp values you have currently designed for), and define your new dp-target width and height.
The stand-alone executable: https://github.com/OneManMobile/ALASCA/raw/master/ALASCA.jar
The source code: https://github.com/OneManMobile/ALASCA
The stand-alone executable: https://github.com/OneManMobile/ALASCA/raw/master/ALASCA.jar
The source code: https://github.com/OneManMobile/ALASCA
The tool is so simple that it should only take you very few minutes to have your app ready for tablets and small devices.
When you have selected your parameters, just press the "Create New Layouts" button and the tool will generate a new layout folder with the name "layout-[some number]" in your current files directory. Like this:
When you have selected your parameters, just press the "Create New Layouts" button and the tool will generate a new layout folder with the name "layout-[some number]" in your current files directory. Like this:
Use the new "layout-[some number]" folder and put it into your project. Rename the folder to "layout-small","layout-large" or "layout-xlarge" to reflect the density that the new layout files are scaled for. Now, any Android device will automaticaly choose the files from the density that fits its screen.
How to make the tool work right
Have every size value defined in dp units. You can use "fill_parent" and "wrap_content" like before but any padding, margin, specific width, specific height and textSize should be defined in Density Indepenent Pixel units (dp).
Find the magic values for scaling, these are mine from practical experience but use an emulator-device and set "abstracted LCD value" if you want to double check different densities:
- Small: 310 dp x 410 dp (Emulator tested on 120 abstracted LCD value)
- Normal: 320 dp x 510 dp (I know I've read 480dp for height, but this works on at least Samsung Galaxy S2, LG Optimus 2, Nexus S and HTC Desire from my experience)
- Large: 540dp x 960dp (Update: 540 x 880 on Nexus 7 seems to work well)
For example, take the base width and height of 320 and 510 and set the target width and height to 800 and 1255 respectively. Then fire off the layout creator.
I apologize for the shifty height values, which aren't really mentioned anywhere as standard, but these are the ones working from my personal experience.
Note: To make sure both width and height is scaled properly, the tool expands "android:padding=XXdp" and "android:layout_margin=YYdp" into their four sub-definitions for left,right,top,bottom in your new files.
Note: To make sure both width and height is scaled properly, the tool expands "android:padding=XXdp" and "android:layout_margin=YYdp" into their four sub-definitions for left,right,top,bottom in your new files.
Points to remember on good scaling
ALWAYS use density independant pixel ("dp"/"dip") units in your layout files. "Px" units are only for a specific resolution, density is not accounted for, and should generally never be used. "Sp" units are used when you want to take font size user-preference into account, but a variable text size generally leaves unpredictable design complications.
When creating your own Custom Views, always remember to have your length units defined relative to the pizel-size aspects of the view (not the density of the device). So in your onDraw method, use getWidth and/or getHeight as base for the scale-factors of any measurements and placements you want to make. This will make your custom view look awesome on tablets.
And so..
This was my first blog post, and it was about a problem that I'm still not completely sure I should have solved. Maybe I have missed something in the documentation that handles this issue or maybe others can benefit from what I made. If you have any feedback on the project, feel free to give it. If what I made is useful, perhaps we will soon see a lot more tablet optimised apps out there.
Special mentions: Mobile Identity, the company I work in - Jesper Borgstrup, a fellow android developer, who provided a tablet (Galaxy Tab 10.1) for testing and inspiration - The experience I've gotten from my personal app projects.
TL;DR - Create layouts for one density, have them scaled automatically for tablets, small devices and everything in between.