這次要介紹的是Android設計介面會用到的單位dp、px,兩者之間有何差異及如何轉換。
何謂 px、dp、dpi ?
px(Pixel) 像素
px是pixel的簡寫,中文稱作像素,也就是螢幕上實際的像素點單位。因此解析度為1920 x 1080的畫面代表長有1920個像素點,寬有1080個像素點,而面積就是1920 x 1080個像素點。
ppi( Pixels Per Inch)
ppi的意思就是每一英吋有幾個像素點,另一種講法就是像素密度。假設有個螢幕的長寬都是1英吋,長寬各有10個像素點,因此我們就能說這個這個螢幕的解析度為10ppi。但例子若改成這個螢幕長寬一樣是1英吋,而長寬各有20個像素點,那麼它的解析度就是20ppi。因此我們發現同樣尺寸的螢幕,ppi越高的話,像素點就越小,畫面看起來也就越精細。
註:1英吋 = 2.54公分
Android的尺寸單位
然而Android的手機有太多種尺寸、不同的尺寸的解析度都不太一樣。因此若是使用px(像素)為單位設計元件大小的話,會發生一個200 px x 200 px 的按鈕在低解析度的畫面(例如320 x 480)會非常的大,而在高解析度(例如1920 x 1080)的畫面上卻又很小的情況。因此在設計Android的介面時就使用單位dp 來解決這問題。
dp ( Density-Independent Pixel ) & dpi( dots per inch )
在介紹什麼是dp之前,首先我們先介紹什麼是dpi。其實dpi跟前面介紹的ppi是同樣的原理,只是Google用不同的名稱來定義。首先看這張圖:
Android的每間廠牌手機的尺寸與密度都不一樣,於是Google定義了一套規格來規範幾種螢幕的密度單位:
- mdpi:像素密度為160 dpi。
- hdpi:像素密度為 240 dpi。
- xhdpi:像素密度為 360 dpi。
- xxhdpi:像素密度為 480 dpi。
- xxxhdpi:像素密度為 640 dpi。
為了讓同個元件在不同密度的螢幕上看起來大小都一樣,Google以dpi定義了單位 dp ,來確保開發人員在建立介面元件時,使用這個單位所設的長寬在不同密度的螢幕上的大小都一致。例如我們假設下圖的字母 a 的長和寬都是100dp,我們分別有兩支手機的螢幕密度為160 dpi 和密度為320 dpi ,那麼縱使它們的密度不同,字母 a 在兩支手機畫面上的大小依然會相同。
總結來說,要釐清各單位之間重點在於
- dpi,也就是像素密度。越大代表畫面的像素點越多,但是像素點也較小;反之dpi越小代表畫面的像素點越少,但像素點也較大。
- 呈上點,所以同樣長寬100dp的按鈕在160 dpi 的螢幕上是尺寸是 100 px x 100 px,但在 320 dpi 的螢幕上的尺寸是 200 px x 200 px 。雖然長寬的值變兩倍了,但是密度也相差兩倍。
白話一點來說,當兩個螢幕密度比例為兩倍時,若是要在高密度螢幕上的按鈕看起來跟低密度的螢幕上的大小一樣的話,高密度上的按鈕長寬(以像素為單位)的值就必須是低密度的兩倍。
單位轉換
px 與 dp 單位之間的轉換公式:
pixel = dp x ( density (dpi)/ 160)
Android有提供dp與px的轉換比例:
val scale = context.resources.displayMetrics.densityval widthInPx = widthInDp * scale
取得螢幕解析度(像素)
有兩種方式能取得手機的螢幕解析度:
- resources.displayMetrics
val displayMetrics = context.resources.displayMetricsval height = displayMetrics.heightPixelsval width = displayMetrics.widthPixels
- windowManager.defaultDisplay
val defaultDisplayMetrics = DisplayMetrics()(context as AppCompatActivity).windowManager.defaultDisplay.getMetrics(defaultDisplayMetrics)val height = displayMetrics.heightPixelsval width = displayMetrics.widthPixels
參考連結:
https://medium.com/uxabc/understanding-ui-units-8acdc0575388