I'm implementing an app for Android(API 10). I have few designs for tablet(supposedly) and for mobile phone. Regarding the previous sentence it might sound a bit stupid: in my opinion layouts should be picked according to device's physical size - not resolution, otherwise there might be a phone with high resolution that renders, say, a grid of 5x5, in rather confusing, inadequately small-sized way. In order to provide division by physical size I gotta use /res/layout-* folders. Agreed ?
Also: I'm a bit confused about multiple-screens guide's definition on physical size. Would you mind explaining what physical size is in terms of Android mean, what it's measured in? Is there any correlation with dpi?
Thanks.
A workaround for api level 10 could be something like this:
use the compat lib from the SDK so that you can design with fragments.
Assume everything before android 3 is a phone. For example use your layout files in layout/* for this (and the rest will be based it on unless overriden). This assumption is basically only wrong for the original Samsung Galaxy Tab 7" from 2009.
Assume everything on android 3.x is a tablet (they are), so do some tablet specific layout if you want and have them under layout-v11 (and maybe also layout-v12 if there is anything specific to android 3.1). Tablet specific layout could mean that you arrange your fragments differently and/or show multiple fragments at the same time.
Everything newer (android 3.2+) you can use the new stuff from api level 13. Such as layout-sw600dp/ for some layouts etc etc. http://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLayouts
Physical size is usually measured in inches, it simply tells you the real device's screen size (usually 3-4" inches for phones and 8-11" for tablets).
dpi, is NOT correlated with it. Dpi expresses screen density, how many pixels are shown in a given area (usually a square inch). It could be considered as a measure of screen quality.
Resolution is given by the product of the two; it expresses the total number of physical pixels on a screen.
Going back to your first question, you should be density independent as much as possible; your app should "look the same" on devices with different densities. The /res/layout-* folders are designed to provide this feature, the system scales drawable resources to the appropriate size and you could then declare in your manifest that your app supports any density:
android:anyDensity="true"
On page http://developer.android.com/guide/topics/resources/providing-resources.html#BestMatch you can learn how Android choose the best matching resource.
With Android API 10 the best option for targeting tablets is probably just distinguishing the actual size of the screen in the code using something like:
https://stackoverflow.com/a/5789916/1319155
and then just load a different drawable if the size value returned was greater than 6 (or whatever size you want to declare as a "tablet").
The reason you can't really just use the size folders (i.e. layout/large) is because the folders don't distinguish between phones and tablets very well. A kindle fire and galaxy nexus may both be considered "large" devices.
The reason you can't really use dpi is because that is not a good reflection on what type of device it is, just how "dense" the pixels are on a screen. Most new phones are much denser (having more pixels per inch) than tablets anyway.
There are two ways of doing this. From Android 1.6 (API 4) on, there are four layouts that describe the physical size of the display: small, normal, large, and xlarge. As described on http://developer.android.com/guide/practices/screens_support.html , these correspond to:
xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp
Note that these are measured in DP, not DPI. DPI is Dots Per Inch, and specifies screen density. DP, also written DIP, are Density-Independent Pixels. Again from the guide:
Density-independent pixel (dp)
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
In other words, 160 DP = 1". Applying this standard, we see:
xlarge screens are at least 6" x 4.5" (7.5" diagonal)
large screens are at least 4" x 3" (5" diagonal)
normal screens are at least 2.9" x 2" (3.5" diagonal)
small screens are at least 2.6" x 2" (3.3" diagonal)
(Not sure why the selection is so odd, but that's what they defined.)
From Android 3.2 on (API 13), there are more options, as described here:
http://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLayouts
Here you can use "smallest screen width," "available width," or "available height" options to define your own categories; again, the unit in question is DP, which is 1/160". Note that these specify the smaller of the two dimensions on the device--e.g., for a 7" tablet they recommend specifying layout-sw600dp, that is, "smallest width 3.75 inches," which would be intermediate between the "large" and "xlarge" sizes defined in API 4. They have a number of specific comments about this topic, including notes about how the widths are measured (it may exclude things like the notification bar), so it's worth taking a look at the documentation.
Related
I've created my app but I decided to test it on all screens to be adaptive. Maybe testing it in
MDPI(160dpi), HDPI(240dpi), XHDPI(320dpi), XXHDPI(480dpi) and XXXHDPI(640dpi) which corresponds to all screen sizes. However I tested my app on two devices support 320dpi. I thought that I get the same result but it don't. so don't know how to test my app on all screens. I'm confused.
I used Genymotion for emulators:
one with 720 * 1280 320dpi
screenshot
and other with 1200 * 1920 320dpiscreenshot
Please help me with that or if there's another way to do it let me know.
thanks in advance
(Bunch of explanation about why this is happening, I put my suggestions in the last section)
DPI isn't the same as size, it's just about how many pixels are packed into a certain area. The higher the DPI, the more pixels there are, meaning they're a lot smaller. So you can get fine detail, but it also means you need more of them to cover a physical distance or area on the screen.
Which is why Android uses dp instead of raw pixel sizes most of the time - the standard minimum touch-target size is 48dp, but how many actual pixels that is depends on the pixel density of the display. For mdpi displays it'll actually be 48 pixels, for xxxhdpi it'll be 4x that amount
It also means if you're doing your design work in dp, the pixel density of the screen doesn't matter - elements with a fixed size will always be broadly the same size on every screen (the mdpi etc buckets are like a "close enough" grouping, the devices in each group won't all have exactly the same DPI) because it's getting translated to the equivalent number of actual pixels. What testing does help with is checking your drawable assets look ok on different screen densities
So you have two devices with the same DPI right?
720 x 1280
1200 x 1920
Because they're the same DPI, those dimensions are converted to dp by the same factor. Let's work it out to be precise (but the exact numbers aren't important): 320 DPI is xhdpi according to that link up there, so 1dp = 2px. Let's convert those screen sizes to dp
360dp x 640dp
600dp x 960dp
It's the same situation but hopefully having those sizes expressed in dp helps you see the problem - when you're designing a layout, you're working with dp, right? The available space you have to work with is defined in dp, and one of those has a whole lot more space than the other! Putting a 300 dp-wide TextView in the layout would almost fill the first one horizontally, but it would only cover half of the second. That's gonna look pretty different!
This is why phones and tablets look so different - even if you have a relatively new phone, and an old Nexus 7 with a much lower resolution, the Nexus 7's screen is going to feel "bigger" and more "spacious". It's a physically larger device, so even though it's low-res, it's also low-density which means those pixels are spread across a larger area. Lower DPI means those pixels translate into more inches. And in the density-independent pixel (dp) system, that means you get way more dp to work with, more space for your layout. Which is what you want on a tablet, you don't want it to look and feel like a massive phone!
That's why it's different - basically one of your devices has more space to work with than the other, because it has more pixels, and the same DPI so those pixels aren't just used for finer detail.
As for testing, you need to look at different screen sizes - which is dependent on the resolution and the DPI. Basically pixels / DPI = size in inches. Do that for your two 320 DPI examples and you'll see one is a fair bit larger, physically, while having the same density
Probably the easiest way to do this, really, is to look at your layout in the design view, and change the Preview Device setting at the top. Some of the Phone devices are more "spacious" than others, newer ones are taller, so go through them and see how your layout changes. Try a Tablet one and see what a lot of extra space does. And if you go down to the Generic Phones and Tablets section at the bottom, there are a bunch of reference devices in there, some of which will be very cramped!
Once you've found a few useful ones, you can set up your emulator / virtual devices with each of their screen resolution / density combinations. I don't know about Genymotion, but the built-in AVD manager gives you a lot of those device definitions as templates when you create a new virtual device. You should at least be able to enter those settings yourself
Also when you publish an app on the Play Store, they'll automatically run it on a bunch of reference devices and give you access to a bunch of screenshots, so you can see if there are any problems with certain screen sizes and fix them before you launch
According to the android documentation, density should be in dpi (dots per inch) and all layout measurement should be in dp.
and using a simple formula android can map dp to actual pixels.
px = dp * (dpi / 160),
160dpi ~ medium density screen which is the baseline
So why not just use ppi (pixels per inch) to describe screen density ?
There is a lot of documentation about this issue, but I think this part is relevant for your question:
Supporting Multiple Screens
Density independence
Your application achieves "density independence" when it preserves the
physical size (from the user's point of view) of user interface
elements when displayed on screens with different densities.
Maintaining density independence is important because, without it, a
UI element (such as a button) appears physically larger on a
low-density screen and smaller on a high-density screen. Such
density-related size changes can cause problems in your application
layout and usability. Figures 2 and 3 show the difference between an
application when it does not provide density independence and when it
does, respectively.
From what I've read it is a design based distinction; the developers shouldn't worry about the individual screens they are deploying to, and should use dp within the application to make it as portable as possible across the different android devices.
For designers of assets the display size and sharpness of image are more important, and the dpi distinction is the one that matters to them.
For more information check out this article/e-book written by a google engineer:
http://sebastien-gabriel.com/designers-guide-to-dpi/
In particular check out the section "The PPI Configuration". Quote from the article:
Anything non-print uses pixel sizes regardless of the initial PPI configuration... PPI configuration in software is a printing legacy. If you design only for the web, PPI won't have any influence on the size of your bitmap.
I have the qualifiers for 7 inch tablets and 10 inch tablets, sw600dp and sw720dp respectively. I don't understand how those numbers were reached.
I would like to create a new layout for phones which a smaller screen size than 4 inches. Please could you explain how I should do this using the smallest width qualifier.
Please checkout "Configuration example" section of official documentation first. It explains very well what is used and when. In your case default layout folder without a qualifier is used for handsets.
What is smallest width qualifier? Smallest width is
The fundamental size of a screen, as indicated by the shortest
dimension of the available screen area. Specifically, the device's
smallestWidth is the shortest of the screen's available height and
width (you may also think of it as the "smallest possible width" for
the screen).
For instance your have a phone with screen size equals to 480x800 dp. The smallest width for this device will be the smallest value of these two, which is 480dp. If you rotate your device, the smallest value will stay unchanged - 480dp.
How to use smallest width qualifier? When you create a layout you always expect a minimum width, with witch it swill looks good. Below this minimum your layout gets squeezed and doesn't look good. To make sure this doesn't happen to it, you put it to the folder with sw<N>dp qualifier, when N the minimal allowed width.
It's worth to mention that because smallest width doesn't depend on orientation, you should take case for handling landscape and portrait orientation by yourself by using land or port qualifiers. Although this approach works, it can become complicated to handle different widths and orientations very soon. To address this issue, there is another approach called responsive mobile design. I suggest to read a series of articles "Deep dive into responsive mobile design" to get better understanding.
Update:
The formula for calculating dp from px is like following:
dp = px / (ppi / 160dp)
Nexus 7 takes sw-600dp, because all calculations are based on getResources().getDisplayMetrics().density value coded in the device. This is not the real value, but a rounded value. For Nexus 7 (2013) the real value is 323/160 = 2.01875. The value coded in the device is 2, which corresponds sw-600dp. This is where some pixels get lost.
sw600dp means smallest screen width of density 600dp. But let me tell you that you need more than this because Nexus 7 (2012) and Nexus 7 (2013) are both 7inch tablets but with different densities. You can add hdpi or xhdpi with sw600dp like values-sw600dp-hdpi. For phones do the same swXXXdp but try not to do that and use screen-size like small, normal, large, and xlarge.
For reference see Android official link
I'm really feeling confused. From the docs at developer.android.com, it seems in order to keep my images scaled correctly (aspect ratio too) across all current Android devices I need all these layouts below. Is that really what everyone is doing? Am I missing something, or should I be going about this a different way?
Low density Small screens QVGA 240x320
------------------------------------------------
layout-small-ldpi
layout-small-land-ldpi
Low density Normal screens WVGA400 240x400 (x432)
------------------------------------------------
layout-ldpi
layout-land-ldpi
Medium density Normal screens HVGA 320x480
------------------------------------------------
layout-mdpi
layout-land-mdpi
Medium density Large screens HVGA 320x480
------------------------------------------------
layout-large-mdpi
layout-large-land-mdpi
High density Normal screens WVGA800 480x800 (x854)
------------------------------------------------
layout-hdpi
layout-land-hdpi
Xoom (medium density large but 1280x800 res)
------------------------------------------------
layout-xlarge
layout-xlarge-land
Your app will work on 100% of the devices with the classic layout.
You can just add some buttons or change the layout in landscape mode by adding some qualifiers but that's up to you!
For instance, on LDPI (small resolution) device, you may want to adjust some buttons or change a little bit to fit the small screen.
You may also want to put some buttons on the right in landscape mode and in the bottom of your layout in portrait!
You do not "have to" use them.
According to Android Dev Protip from Roman Nurik about screen size qualifiers:
If you have custom layouts for larger screen devices such as tablets,
now's the time to stop using the -large or -xlarge resource qualifier
and switch to using -swXXdp or -wXXdp qualifiers. The latter were
introduced in API level 13, which basically all tablets now have
support for according to the latest platform version charts1.
means that for basically all cases where -large would have any effect,
-swXXdp can be used instead to provide more granularity.
So which actual sw or w qualifiers should you use? Here's a quick
just-give-me-something starting point:
7" tablets: Instead of layout-large, use layout-sw600dp.
Example: Nexus 7 = 960×600 dp; the smaller of the two dimensions is
600.
10" tablets: Instead of layout-xlarge, use layout-sw720dp.
Example: Nexus 10 = 1280×800 dp; the smaller of the two dimensions is
800. Some 10" tablets are a bit more narrow so 720 is a commonly used switching point.
There's more to it than just that (you really want to choose switching
points based on your content's minimum requirements, not on device
form factor), but that's a #Protip for another day (::cough:: +Nick
Butcher ::cough::).
In the layout if you do not use AbsoluteLayout, you application is going to be resized to fit the screen.
But in some cases, for smaller screens you need declare a new layout with less components for example.
For images:
You has some options.
Simple ignore some resolutions and let the device choose the best image to it.
Declare on AndroidManifest for wich sizes you want to support.
Or has just one and let the resize screw your application.
Yes. You should define different layout for different screen resolution.
When you are supposed to work with tablet kind of application. That time really you feel that. There is a need of different layout. Because Tablets always comes in different size.
One more thing, When you are working on android, means you should always taste your app with real device. And also test with different size emulators.
As per "android multiple screen design":
"As you design your UI for different screen sizes, you'll discover that each design requires a minimum amount of space. So, each generalized screen size above has an associated minimum resolution that's defined by the system. These minimum sizes are in "dp" units—the same units you should use when defining your layouts—which allows the system to avoid worrying about changes in screen density.
xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp"
DisplayMetrics class gives me access to actual width and height of the screen. However is the above table available programmatically. Or do I need to store these values as constants in my app. The second option seems hacky.
Your problem is that you try to make a fixed design for x known resolutions whereas Android's Framework is based on the idea that you don't know in advance the exact dimensions of the device your app will be running on. And if you look at the Android market, that's a good assumption to make.
If you make good uses of :
-selectors like "sw600dp"(7" tablet)
-nine-patchs (stretchables assets)
-dimensions in dip for things that need to have a fixed size (for example a button needs to be 48dp at least in order to be big enough)
you can make very good designs that adapt to all form factors from 2" phones to 10" tablets.