3

I tested a simple layout on different densities. Here's the layout xml code for activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="32dp"
    tools:context="com.noah.densitytest.MainActivity"
    android:background="@color/gray" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:padding="4dp"
        android:background="#000000" >

        <TextView
            android:id="@+id/tv1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world"
            android:textSize="16sp"
            android:layout_marginTop="32dp"
            android:background="@color/algea_green" />

        <View
            android:id="@+id/square_top"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:layout_marginLeft="16dp"
            android:layout_toRightOf="@id/tv1"
            android:background="@color/aqua" />

        <View
            android:id="@+id/square_center"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_centerInParent="true"
            android:layout_marginRight="32dp"
            android:background="@color/blue" />

        <View
            android:layout_width="32dp"
            android:layout_height="256dp"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@id/square_center"
            android:background="@color/dark_slate_blue" />

        <View
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:layout_toRightOf="@id/square_top"
            android:layout_marginLeft="48dp"
            android:layout_marginTop="128dp"
            android:background="@color/medium_purple" />

    </RelativeLayout>

</RelativeLayout>

I just put it in a single folder - res/layout.

I used dp which is said to be density independent and that Android will automatically scale values given in this unit. However, the problem is that the layout appears differently per density. I used mdpi, hdpi, xhdpi, and xxhdpi AVDs. But all the other attributes are 8in, 1280x720, normal, long - across all test devices. So why is it that they appear differently? It really looks very ugly on the other densities. I also tried copying it to specific folders like layout-mdpi, layout-hdpi, etc but still the same result.

However, if I use px as the unit, then the layout on all devices look the same. Why does it seem better using px?

I hope you could explain this to me or can provide me good links where I could deeply understand how Android does this and why dp is more recommended than px which is in constrast to this result.

Here's what the result looked like:

grg
  • 5,023
  • 3
  • 34
  • 50
Gwapo Gwapo
  • 121
  • 1
  • 10

2 Answers2

3

You are confusing between density, resolution and physical size.

dip/dp or device-independent pixel is always the same regardless of resolution. All units written in dip/dp is based on mdpi, which is the baseline density. The value for each density is:

  • mdpi : 160dpi (dots per inch)
  • tvdpi: 231dpi
  • hdpi : 240dpi
  • xhdpi: 320dpi

This means, how small/big is the resolution, if the screen density is the same, the value will be the same too.

Example: For a device with (1280x720, mdpi) and other device with (640x480, mdpi), 16dp is 16px in both devices.

On the other hand, different density will affect the physical size/px of dp unit. The factor is the ratio of its density to mdpi.

Example: If using dp unit, hdpi device will have 1.5 (240/160) times larger than mdpi. xhdpi device will have 2 (320/160) times larger than mdpi.

This means, as shown in your image, device with same resolution but different density will have different size! Denser density will take more space.

In contrast, when you use px in constant resolution, you will see no difference on each density, because it is not included in the calculation.

Example: For a device with (1280x720, mdpi), (1280x720, hdpi), and (640,480, xhdpi), 16px is... well, 16px.


More reading:

Community
  • 1
  • 1
Andrew T.
  • 4,701
  • 8
  • 43
  • 62
  • wow thank you very much for that great explanation! so how then do I fix this problem w/o using px? since Google discourages using px. this difference in space would really affect user exp. Especially that diff between mdpi and xxhdpi, the border is really thick and the pink box is almost out of the screen – Gwapo Gwapo Aug 07 '14 at 06:27
  • I also tried using values-mdpi etc then @dimens on the layout but still no effect. I tried padding 32dp on values-mdpi, padding 48dp on values-hdpi, etc but it got much worse, border got very thick on xxhdpi – Gwapo Gwapo Aug 07 '14 at 06:30
  • If you're more concerned to the physical size, maybe you can use the simpler "size" qualifier (`layout-small`, `layout-normal`, etc) or the more flexible "smallest width" qualifier (`layout-sw600dp`, `layout-sw720dp`, etc). You can read more about that on the first link in the answer. As for `@dimens`, probably you want to scale the size smaller, not larger, for denser density, although it kind of defeats the purpose. – Andrew T. Aug 07 '14 at 07:19
  • hi sir I'm currently having problems with my WMS request opacity, please help at http://stackoverflow.com/questions/27936381/how-do-i-set-the-opacity-of-a-wms-requested-layer-in-android-google-maps-api. Thank you :) – Gwapo Gwapo Jan 20 '15 at 00:47
-1

That won't always work correctly. You need to have separate layout folders in order for it to work the way you want. The folders are layout-large layout-large-land layout-xlarge layout-xlarge-land layout-small layout-small-land

You don't need all these folders if you dont want, I tend to leave out both small folders and layout-xlarge-land. But with these folders Android will automatically load the correct XML that applies to the screen size you're using. Ex. layout-large would be used on a device such as the Nexus 7.

dogger20011
  • 255
  • 2
  • 13
  • Hi, thank you for the quick response. I used the same screen sizes but only different densities. So I thought using folders like layout-mdpi, layout-hdpi, etc will work. But still the same result. – Gwapo Gwapo Aug 07 '14 at 02:50