天天看點

android裡height機關,Android UI 開發裡的尺寸機關了解

在學習 Android UI 開發的初期,經常被一些常用概念如 dp、sp 和它們與 px 的換算等虐,要避免被虐,最好的方法當然是知其是以然,再見到它們就胸中有料心不慌了。

背景知識螢幕大小(Screen size)

螢幕對角線的實際實體大小。通常以英寸(inch)為機關。

螢幕密度(Screen density)

每英寸上的像素個數。通常被稱作多少 dpi(dots per inch)或多少 ppi(pixels per inch)。

比如,LG Nexus 5 的螢幕尺寸為 4.95 英寸,分辨率為 1920*1080,則它的對角線上的像素數為 sqrt((sqr(1920)+sqr(1080)),是以它的螢幕密度為 sqrt((sqr(1920)+sqr(1080))/4.95=445.03,約為 445dpi。

分辨率(Resolution)

螢幕上的實體像素個數。

比如 LG Nexus 5 的分辨率為 1920*1080,這裡的 1920 和 1080 就是螢幕長和寬上的像素個數。

尺寸dp(Density-independent Pixels)

在不同大小、密度和分辨率的螢幕上的實體大小都近似相等的虛拟尺寸機關。

約為 1/160 英寸(為什麼是約為?稍後講解)。

sp(Scale-independent Pixels)

基于首選字型大小的縮放像素。

與 dp 類似,但是會根據使用者的首選字型大小縮放。

pt(Points)

1/72 英寸。

px(Pixels)

像素。

mm(Millimeters)

毫米。

in(Inches)

英寸,約 2.539999918 厘米。

換算

dp 轉 px

為了簡單起見,Android 将螢幕密度概括為 6 種:ldpi(low) ~120dpi

mdpi(medium) ~160dpi

hdpi(high) ~240dpi

xhdpi(extra-high) ~320dpi

xxhdpi(extra-extra-high) ~480dpi

xxxhdpi(extra-extra-extra-high) ~640dpi

但是并非表示所有 Android 手機隻有這幾個螢幕密度,比如上面舉例的 LG Nexus 5 的螢幕密度是 445dpi,近似地歸于 xxhdpi,Android 在内部進行 dp 到 px 的換算時将采用 480dpi 而非 445dpi。

簡而言之,dp 數 x 換算成 px 數 y 的公式:

// 向上取整

y = x * generalizedDensity / 160

這裡的 generalizedDensity 就是以上 6 種中的一個值,比如 LG Nexus 5 的實際螢幕密度為 445dpi,但是歸于 xxhdpi,是以它的 generalizedDensity 就是 480dpi。

官方文檔給出的轉換 dp 到 px 的代碼示例為:

// The gesture threshold expressed in dp

private static final float GESTURE_THRESHOLD_DP = 16.0f;

// Get the screen's density scale

final float scale = getResources().getDisplayMetrics().density;

// Convert the dps to pixels, based on density scale

mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

// Use mGestureThreshold as a distance in pixels...

在 mdpi(160dpi)上 1dp=1px(還記得前面講過的 1dp 約為 1/160 英寸嗎?在 160dpi 的螢幕上,1px=1/160 英寸),這裡的getResources().getDisplayMetrics().density實際上就等于我們的generalizedDensity / 160,表示将 dp 轉換為 px 的一個轉換因子。

然後來了解一下為何 dp 是約為 1/160 英寸。

還是以 LG Nexus 5 舉例,比如 160dp,若在一個螢幕密度恰好是 480dpi 的機器上,那它會是準确的 1 英寸,但是 LG Nexus 5 的螢幕密度是 445dpi,根據上面的公式計算得出:160dp = 160 * 480 / 160 px = 480px,則它的實際顯示尺寸為 480/445=1.07865 英寸。是以原因是dp 換算成 px 是使用 Android 概括的六種螢幕密度之一,而非實際螢幕密度,是以在不同的手機上相同數量的 dp 顯示尺寸會有輕微差異。

sp 轉 px

y = x * scaledDensity

這裡的 scaledDensity 擷取方式為getResources().getDisplayMetrics().scaledDensity。

這個猜想是否正确呢?看看下面一張圖就明白啦!(Nexus 4 模拟器截圖)

android裡height機關,Android UI 開發裡的尺寸機關了解

根據分辨率和螢幕密度求螢幕尺寸

使用 adb 指令 adb shell wm size 可以得到裝置分辨率,adb shell wm density 可以得到裝置螢幕密度,但貌似沒有辦法直接得到螢幕尺寸,隻能拿到這兩個資料之後換算。

公式:

sqrt(sqr(width)+sqr(height))/density

繼續閱讀