1. 程式人生 > >Android density與顯示效果總結

Android density與顯示效果總結

1.螢幕密度是否可以修改?

2.螢幕密度與解析度的關係?

3.px與dip之間的轉換與螢幕密度的關係?

1.螢幕密度是否可以修改

   Android中儲存螢幕密度的系統變數為:ro.sf.lcd_density,

    此變數可以在相應的mk檔案中進行修改:

  PRODUCT_PROPERTY_OVERRIDES := \
    ro.sf.lcd_density=320 \

2.螢幕密度與解析度的關係

先看一組解析度與DPI(dot per inch ,每英寸畫素數)的對應關係:

4:3
VGA     640*480 (Video Graphics Array)
QVGA  320*240 (Quarter VGA)
HVGA  480*320 (Half-size VGA)
SVGA  800*600 (Super VGA)

5:3
WVGA  800*480 (Wide VGA)

16:9
FWVGA 854*480 (Full Wide VGA)
HD        1920*1080 High Definition
QHD     960*540
720p    1280*720  標清
1080p  1920*1080 高清

解析度對應DPI
"HVGA    mdpi"
"WVGA   hdpi "
"FWVGA   hdpi "
"QHD      hdpi "
"720P     xhdpi"
"1080P   xxhdpi

再看Android原始碼中的DPI與螢幕密度對應關係的定義:

    public static final int DENSITY_LOW = 120;

    /**
     * Standard quantized DPI for medium-density screens.
     */
    public static final int DENSITY_MEDIUM = 160;

     public static final int DENSITY_TV = 213;
    public static final int DENSITY_HIGH = 240;

      public static final int DENSITY_XHIGH = 320;

    public static final int DENSITY_XXHIGH = 480;

    public static final int DENSITY_XXXHIGH = 640;

    /**
     * The reference density used throughout the system.
     */

預設的density:

public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;

    private static int getDeviceDensity() {
        // qemu.sf.lcd_density can be used to override ro.sf.lcd_density
        // when running in the emulator, allowing for dynamic configurations.
        // The reason for this is that ro.sf.lcd_density is write-once and is
        // set by the init process when it parses build.prop before anything else.
        return SystemProperties.getInt("qemu.sf.lcd_density",
                SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
    }

前面說到ro.sf.lcd_density可以設定,那麼在FWVGA屏的時候,是否可以設定成320呢,答案是可以的,

只是在顯示效果上有很大的區別,同一解析度的屏,lcd_density設定得越大,在螢幕上顯示出來的

字和圖片也就越大,具體的原因看第三個問題的分析。

3.px與dip之間的轉換與螢幕密度的關係

先看轉換的公式:dip值 =裝置密度/160* px值

為驗證此等式,做了一個測試:

    <TextView
        android:id="@+id/testText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        />
   <Button
       android:id="@+id/button1"
       android:layout_width="100px"
       android:layout_height="100px"
       android:text="button_1"
       android:layout_below="@id/testText"
       />
      <Button
       android:id="@+id/button2"
       android:layout_width="100dip"
       android:layout_height="100dip"
       android:text="button_2"
       android:layout_toRightOf="@id/button1"
       android:layout_alignTop="@id/button1"
       />

當density設定為:240時,效果圖

當density設定為:320時,效果圖

從效果圖上可以看出,當density為240時:dip值 =1.5* px值

                                       當density為320時:dip值 =2 * px值

網上也有很多工具類,如

 /**
  * 將dip或dp值轉換為px值,保證尺寸大小不變
  * 
  * @param dipValue
  * @param scale(DisplayMetrics類中屬性density)
  * @return
  */
 public static int dip2px(float dipValue, float scale) {
  return (int) (dipValue * scale + 0.5f);
 }

上面的scale=getResources().getDisplayMetrics().density;

此處確實會引起很多的誤解,density不是密度嗎?這和上面的公式完全不對啊,

先看看原始碼中對此處的density的賦值:

   density =  DENSITY_DEVICE / (float) DENSITY_DEFAULT;
        densityDpi =  DENSITY_DEVICE;
        scaledDensity = density;

其中:DENSITY_DEVICE = getDeviceDensity()     //即裝置密度

      DENSITY_DEFAULT = DENSITY_MEDIUM      //即為160

這樣替換進去就和上面的一樣了,後面加的0.5為了使變數不為零

獲取裝置的density的真正方法應該是:

getResources().getDisplayMetrics().densityDpi