I'm developing an application for tablet 7 inch Kindle Fire HD and Nexus 7 . These two applications are the same size and the same screen resolution. However, I run my application, it is very different. Why?
it seems this is because the nexus 7 is detected as TVDPI, and the Kindle Fire HD is HDPI. How to have a same rendering based on a model 1280 * 800?
Thank you
Well, it seems you've already discovered why the two have differences, it's because they report different density scale factors:
So why do they report differently when they technically have the same physical size and resolution?
The CORE issue actually exists because one device is a Google Play device (Nexus) and the other is not (Kindle). All Android devices that have Google Play (and other Google apps) can only do so by passing something called the Compatibility Test Suite (CTS), which verifies that settings like this one conform to the standards they have put forth. The standards themselves are documented in a Compatibility Definition Document (CDD) for each release. Here is a link to the CDD for Android 4.0 (Section 7.1 deals with screen size and density). The CDD tell a device manufacturer that they should report the scale factor that is numerically closest to the screen's actual DPI, which is in fact TVDPI in this case.
Amazon devices do not use any Google applications, including Google Play. While it may be in their best interest to follow the same standards, they are not bound by them, and the often are not followed. TVDPI kind of snuck up on everyone when it showed up on the Nexus 7, but Amazon would have known about it if they referenced the CDD during design.
How does this cause them to behave differently?
The differences aren't in your layout selection. Obviously from your screenshots both devices are picking up the proper layout as you expect them to. Changing the sw
value on a layout directory only affects which devices will select that layout...it doesn't change anything about how things will be scale. Don't bother trying to place layouts themselves in density specific directories...layouts are supposed to be flexible.
Instead the problem lies with any dimension or size calculation made on density-independent pixel units (i.e. dip or dp), such as text sizes, any fixed view sizes you may have created, and drawable sizes.
Because these two devices have chosen to scale assets differently, any drawable resource you use or any value you define in "dp" will result in a small change. Let me give you two examples:
You define the text size for a TextView
to be 16dp
. On the Nexus 7, this will draw the text at 21px. The Kindle Fire HD will draw that same text at 24px. The difference is small...but it exists.
The same is true for drawable images. If you only defined an image in drawable-mdpi
at 48x48 and the same image in drawable-hdpi
at 72x72, the Kindle has a 72px image to use directly, and the Nexus will create a scale 64px image, so there's a difference of 8 pixels between the two assets.
What can I do to make the two look more similar?
In most cases, I would say you shouldn't. Typically the scaling done does not largely affect the outcome of the application unless the constraints of the layout are set up with too many hard-coded sizes.
However, in general if there are parts of your UI that you need to specifically change for this purpose, the solution is to define specific resources and dimensions for the -tvdpi
case where you feel they are required (again, I wouldn't recommend scaling EVERYTHING in your app to meet this case).
For things like text or view sizes, it means you may want a values-tvdpi/dimensions.xml
file and a default values/dimensions.xml
file. Using the example above, you could define the default text size as 16dp, but in the -tvdpi
location, define the same dimension as 18dp. This will cause both devices to scale the final text up to 24px. In your code, where the actual dimension is used, reference it as @dimen/myTextSize
rather than 16dp
directly.
For drawable items, add a drawable-tvdpi
directory and scale those assets to match how you think they should draw on devices like the Nexus 7. Again with our previous example, copy the same image file from the drawable-hdpi
folder into the drawable-tvdpi
folder so both devices will draw the same image at 72px.
To avoid copying the same asset in multiple places, you can also do this with aliasing. Putting the image itself into drawable/
with a special name, and using values-tvdpi/drawables.xml
and values-hdpi/drawables.xml
to reference the single asset in two places. For more information on aliasing, see this documentation. The examples are for layouts, but the same paradigm works for drawables (or any resource) by changing to type="drawable"
.
Because the Nexus7 is a tvdpi device it uses the layout-sw600dp assets (based on calculations at 213dpi), the FireHD is an HDPI device and ends up using layout-sw533dp assets (calculations based on 240dpi)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With