解析度,dpi,dp,與最終顯示大小的四角關係

Hly_Coder發表於2019-03-04

概述


可能大家都知道,一款app要想適配儘可能多的手機,在寫佈局檔案的時候都會使用dp來代替px. 如果遇到需要特別處理的則寫在指定資料夾(如:values-sw600dp, values-sw720dp-land)下面的dimens.xml中,但是具體到1dp在螢幕上能顯示多大,一張100*100px的圖片在不同資料夾(drawable-xhdpi, drawable-xxhdpi)中能顯示多大,佔用多少記憶體可能相對較模糊,這篇文章就來講講他們之間的關係

概念


在搞清楚他們的關係之前,還是先來這幾個名稱的概念

解析度

手機的螢幕上能容納的畫素點。
比如1080*1920(俗稱1080p),就是指橫向能容納1080個畫素點,縱向能容納1920個畫素點

dpi

是Dots Per Inch的縮寫,翻譯過來就是每英寸(Inch)有多少點。來舉個栗子

解析度,dpi,dp,與最終顯示大小的四角關係
AVD.png

在AS裡面建立模擬器的時候,會出現上圖來選擇裝置。
其中Size就是指的手機對角線的長度,單位是英寸("),Nexus5為例,對角線上的畫素點有:sqrt(1080 1080 + 1920 1920) = 2202.907,那麼對角線上每英寸有的畫素點就是:2202.907 / 4.95 = 445.03,那nexus5的dpi就是445.03咯? 其實不是,但是也是
實際上nexus5的dpi就是445.03,但是在android中使用的時候,會根據如下範圍標準
解析度,dpi,dp,與最終顯示大小的四角關係
support_dpi.png

所以nexus5會顯示為xxhdpi(480dpi)

每種通用的密度都涵蓋的是密度範圍,也就是說2部都是480dpi的手機,其實際的dpi有可能不一樣.

解析度,dpi,dp,與最終顯示大小的四角關係
actual_density.png

dp

所有的android開發在定義長寬的時候都在使用dp,那麼dp到底是什麼呢?
要講清楚這個還得從android歷史開始。
第一代 Android 裝置 (T-Mobile G1) 的螢幕是採用的HVGA 螢幕(在 Android 1.6 之前,這是 Android 支援的唯一螢幕配置),這個螢幕上1dp=1px,並且是被歸為mdpi型別,從此,這個就成為了android的最初始標準。隨著不同廠商的加入,越來越多的不同dpi裝置出現,於是有了下面這個標準

ldpi mdpi hdpi xhdpi xxhdpi xxxhdpi
0.75px 1px 1.5px 2px 3px 4px

這是怎麼來的呢?以xxhdpi來說,因為xxhdpi是歸為480dpi的一類裝置,是原始標準160dpi的2.5倍,所以1dp就對應2.5px

T-Mobile G1的硬體引數如下:
螢幕尺寸:3.2 寸(8.1 釐米)
解析度:320 x 480(HVGA)
計算出dpi = 180.27,所以歸為mdpi類

顯示大小

就是一個view顯示在螢幕上有多大,這個沒什麼好說的.

小結


要記住上面的關係可能很難,還好可以通過程式碼來獲取值,我們只要記住這幾個值是什麼意思就可以了。
先來看如何獲取dpi

float dpi = context.getResources().
                      getDisplayMetrics().densityDpi;複製程式碼

這個值就會是160.0 240.0 320.0這些值.
那如何獲取1dp對應著多少px呢?可以通過如下方式

float scale = context.getResources().
                        getDisplayMetrics().density;複製程式碼

這個值就是0.75 1.0 1.5這些值。
比如在hdpi上,1dp=1.5px,但這其實是佔有2個畫素的。所以在真正編碼的時候會用以下方式來做轉換

// The gesture threshold expressed in dp (定義的16dp的值)
private static final float GESTURE_THRESHOLD_DP = 16.0f;
// Get the screen's density scalefinal (獲取縮放比例)
 float scale = getResources().density;
// Convert the dps to pixels, based on density scale (定義的值 * 比例 + 0.5f)
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);複製程式碼

這裡加0.5是為了將該數字四捨五入到最接近的整數。

顯示大小


那麼,同一張圖,在不同的資料夾,同一個手機上會有什麼表現呢?
以一個144*144px的icon圖示(放在drawable-xxxhdpi目錄下),在xxhdpi密度的手機為例。用如下程式碼進行測試

//imageView都是wrap_content屬性, src=144*144px的icon圖示
ImageView imageView = (ImageView)findViewById(R.id.img);
imageView.post(new Runnable() {
      @Override
      public void run() {
          Log.i("hly", "img: " + imageView.getWidth() + " " + imageView.getHeight());
      }
 });複製程式碼

這裡直接給出答案: 108px 【144 * (480 / 640)】
根據該文可以得出,計算公式是:

最終顯示畫素 = 原始畫素 * (顯示裝置dpi / 放置資料夾對應dpi)複製程式碼

這也就是如果對應資料夾裡面沒有圖片的時候,顯示預設圖片大小不一致的原因。

總結


也沒啥好總結的了,想要熟悉這些關係,需要先記住基準尺寸mdpi- 160dpi。
以上

歡迎關注公眾號

解析度,dpi,dp,與最終顯示大小的四角關係
qrcode_for_gh_665b92827be4_344.jpg

相關文章