2015年2月16日 星期一

[Android] 讓不同螢幕尺寸與解析度顯示相同比例的UI

Android支援太多手機,造成開發者必須因應不同的手機螢幕設計UI.
同樣是4.3吋的螢幕,有800*480的解析度,也有1280*720的解析度。
又或者一樣是1280*720解析度,但螢幕尺寸有5.5吋,也有7吋的。
在這麼錯縱複雜的螢幕下,如何設計出清晰且正常比例的UI呢?
首先要釐清一些概念與名詞。

像素 (Pixel)
也稱畫素,螢幕呈現影像的最小單位,也可說是點陣圖的最小單位。
數位影像尺寸通常是以像素計算,例如: 48*48 pixel 就是一個正方形的影像大小。

因為像素是數位影像的最小單位,可以想像成一個像素就是一個點,
48*48 pixel就是長和寬都由48個點所組成的。如下圖:




螢幕尺寸
也就是我們大家熟知的幾吋幾吋,手機是4吋的,
電腦螢幕是22吋的,電視螢幕是32吋的。

像素與螢幕尺寸的關係
請問,48*48 pixel的影像到底有多大? 他是一個正方形,長與寬相同,
不過你能告訴我長寬是幾公分嗎? 或是幾英寸呢? 不知道。
前面提到像素是最小單位,最小單位總也有個長度吧?
你會發現找了一堆資料,沒有人跟你說一像素是多大,只會說是最小單位。
其實48*48 pixel的圖片,它可以是長寬10公分,也可以是1公分。
取決於像素和螢幕尺寸的關係。

現在有兩支手機如下:
手機A,4.3吋,解析度800*400
手機B,4.3吋,解析度1280*720

手機A,請問800*480是什麼單位?
其實就是像素 (Pixel), 我個人覺得我們濫用了解析度這個詞。
800*480就是Pixel單位,它說明4.3吋的手機螢幕中,長有800個像素填充,
寬有480個像素填充。手機B解析度則較高,
因為它的長有1280個像素填充,寬有720個像素填充。
你可以把像素想成點,這兩支手機螢幕尺寸都是4.3吋,
可是兩支手機填充的像素不同,同樣尺寸下,像素填充越多,
解析度就越高。

這兩支手機如果顯示一張圖48*48 pixel會怎麼樣呢?
手機A會比較大張,手機B會比較小張,請看下圖:

圖中的鉛筆都是48*48 pixel,同樣是4.3吋手機A和手機B,
手機A,800個點(Pixel)填滿4.3吋的長,
手機B,1280個點(Pixel)填滿4.3吋的長,
它們的長一樣,使得手機A的點(Pixel)比手機B的點還要大點。
也就是你比較容易用肉眼看到手機A的一格格的畫格 (Pixel),
所以同樣Pixel的圖,手機A會比較大張,手機B比較小張。
手機A解析度比較低,手機B解析度比較高。

PPI
800*400就是填充像素,我會說解析度800*400濫用,
是因為螢幕解析度跟螢幕尺寸與填充像素有關,而不是只和填充像素有關。
1280*720的解析度一定比800*400高嗎? 如果同樣的螢幕尺寸是對的,
但不同的螢幕尺寸就不一定了喔。PPI才是正確拿來描述解析度的,請看下圖:


此圖來自iPhone官方網站,從左至右為iPhone 6 Plus, iPhone 6, iPhone 5s, iPhone 5c.
可以發現iPhone 6和iPhone 5s的螢幕尺寸與像素皆不同,但解析度都是326 ppi.
ppi的公式為 √(像素長度2+像素寬度2)/ 螢幕尺寸 ,將iPhone 5s和iPhone 6套用公式如下:
  • iPhone 5s,(1136*1136 + 640*640) / 4 = 325.96
  • iPhone 6 ,(1334*1334 + 750*750) / 4.7 = 325.61
iPhone 6雖然填充像素增加,但螢幕尺寸也增加,所以與iPhone 5的解析度相同。
也因為兩支手機的解析度相同,所以使用同樣像素尺寸的icon即可。
例如iPhone 6使用128*128的圖片,iPhone 5s也是要使用128*128的圖片,
如此圖片就會在這兩支手機中有相同的顯示比例。
所以,PPI的值越大,需要的圖片要越大張
另外,DPI通常用於列印出版用,在螢幕的世界裡,DPI = PPI.

讓Android自行選擇適合的圖片大小
螢幕世界中,DPI = PPI ,由於官方文件都使用DPI,
所以在此段落我們一概使用DPI當作解析度,但意思跟PPI是一樣的。
寫過Android程式就知道透過不同的drawable資料夾可以支援多尺寸螢幕。
現在我們知道PPI才是決定圖片大小,而非螢幕尺寸,也非像素填充。
資料夾的命名應該如下:
  • drawable-ldpi
    • 約 120 dpi
  • drawable-mdpi
    • 約 160 dpi
  • drawable-hdpi
    • 約 240 dpi
  • drawable-xhdpi
    • 約 320 dpi
  • drawable-xxhdpi
    • 約 480 dpi
別再使用small, normal, large等螢幕尺寸來規劃圖片大小,
可參考Google的Supporting Multiple Screens.

資料夾間,圖片大小相對比例應該為何呢? Google也有提供說明如圖:
這些倍率是怎麼算出來呢? Android有自己的圖片單位Density-independent pixel(dp),
在layout中UI的單位建議使用dp,因為它會幫你算出正確的pixel大小,公式如下:
  • pixel = dp * (dpi / 160)
由此可見,當dpi = 160 (也就是mdpi)時,pixel = dp. 更大的dpi只要透過此公式,
便可算出需要比mdpi使用多大的比例的圖。

DPI與PPI的差別
PPI = Pixel Per Inch,每英吋使用多少像素,用於螢幕。
DPI = Dot Per Inch,每英吋使用多少點,用於印刷。

在螢幕的世界裡,最小單位就是像素,
也就是點(所以前面才提到可以想像成點)。
嚴格來說,在螢幕上解析度應該都要說PPI,
只是現在都混用,所以只能說在螢幕中,
PPI = DPI。

在印刷中,是以一英吋裡可以噴出幾滴油墨計算,
一滴油墨就是一個點,所以使用DPI作為單位。
當影像由螢幕要列印出來時,PPI和DPI是不同的。
因為印刷機的不同,一像素未必等於一滴油墨(點)。

結論
  • 螢幕解析度由PPI決定,而不是螢幕尺寸也不是像素填充
  • PPI越高,所需要的圖案也越大,才能顯示相同比例的UI
  • drawable應該要以ldpi, mdpi, hdpi來分類,而不是small, normal, large來分類
  • 螢幕使用PPI,印刷使用DPI,只有在螢幕世界中PPI = DPI.

7 則留言:

  1. 請問一下pixel = dp * (dpi / 160) 公式中,dpi是否只是手機設備的值,而不需考慮圖片檔案的dpi值。是否圖片只需要考慮公式左邊的pixel,圖片的dpi不需要與手機設備的dpi一致?
    例如,一張圖片 48pixel x 48 pixel,不管該圖片的dpi是160或320,只要是使用在同樣設備的手機上,例如 dpi為160的手機,在手機上顯示的dp值,都會是一樣? 謝謝

    回覆刪除
    回覆
    1. 公式的 dpi 指的是手機設備的 dpi.

      電腦圖片的解析度通常就是指 pixel 長乘寬,像是 72 pixel * 72 pixel 會比 48 pixel * 48 pixel 大張,但是一樣清楚。

      不過如果觀察圖片檔案屬性,會看到水平解析度與垂直解析度,這在列印或掃描時才會用到,告知列印或掃描時一英寸需要多少 pixel 填充,此時會根據 dpi 換算出這張圖列印出來會多大張 (幾公分幾英吋)。

      例如兩張圖片都是 48 pixel x 48 pixel, 分別為 160 dpi 和 320 dpi, 在電腦和在手機顯示的圖片尺寸都是一樣的。但是列印 320 dpi 那張圖片尺寸會比較小。

      總之,實作 App 只要看圖片 pixel 乘 pixel 就好,不用看圖片本身的 dpi, 那是列印時才需要思考的。

      刪除
  2. 請問一下,
    如果在螢幕世界裡面,dpi=ppi的話,那為什麼Android Developers在教學上,要我們在photoshop裡面,這樣設定解析度呢?
    MDPI (160), 設定 Photoshop resolution to: 72 ppi
    HDPI (240), 設定 Photoshop resolution to: 108 ppi
    XHDPI (320), 設定 Photoshop resolution to: 144 ppi
    XXHDPI (480), 設定 Photoshop resolution to: 216 ppi
    XXXHDPI (640), 設定 Photoshop resolution to: 288 ppi
    以下為原始網址:
    https://plus.google.com/+AndroidDevelopers/posts/6Eng1FFa2cY

    回覆刪除
    回覆
    1. 若您實際用 Photoshop 按照 Android Developers 的教學操作,會發現當您調整 Photoshop Resolution 時,
      Pixel Dimensions 也會跟著改變,也就是圖片的像素大小改變了。這和本篇文章的 PPI 的值越大,需要的圖片要越大張的概念沒有衝突。

      Photoshop 中,圖片的 PPI (Photoshop Resolution) 是由圖片像素大小 (Pixel Dimensions) 和圖片文件大小 (Document Size) 計算而來。當您按照 Android Developers 調大 PPI 時,會發現文件大小不會變,但像素大小會跟著變大,圖片也就變大張了。

      在螢幕中,是不看文件大小 (Document Size) 的,那是列印輸出時才需要用到的,螢幕只看圖片像素大小 (Pixel Dimensions) 。所以 Android Developers 教您當手機 Destiny 越大,調大 Resolution 是沒有錯的,因為文件大小 (Document Size) 不變的情況下,像素大小 (Pixel Dimensions) 會變大,和本篇文章是沒有衝突的。

      DPI 和 PPI 名詞解釋文章有解釋,DPI = PPI 是指在"螢幕中"的"同一張圖片",而不是指手機螢幕解析度 (如 MDPI) 和圖片解析度 (例如 Photoshop Resolution) 相等,因為這是兩個不同的東西啊,別會錯意囉。

      或許您還是會覺得模糊混淆,但相信多查點資料,多看點其他說法,您會慢慢意會的。當初我也是看了很多文章,理解各種說法匯集才懂。不好意思這麼久才回覆,若有問題可以再討論。

      刪除
  3. 這是我看過所有關於pixel,dpi,ppi,解析度...,解釋很清楚且易懂的一篇文章,讓我一些似懂非懂的概念,釐清了許多,非常感謝!

    回覆刪除
  4. 這篇文章寫得很好~謝謝你的分享~不過希望作者修正一些名稱上的問題~
    我們在解釋尺寸時大家都習慣說長X寬,其實這是有問題的,怎麼說!
    你開啟Photoshop的新增文件他問你的是寬度(水平 X軸)與高度(垂直 Y軸),並沒有長這個表示方式。
    長應該要跟短這個字放在一起,長短無法完全表示方向性,而寬度與高度會出現方向性縱(垂直 Portrait Y軸)向與橫(水平 Landscape X軸)這是以2D平面的方式來表示,所以不要再說長X寬了,如果硬要說也必須是在立體表示時才會出現長(Y軸)X寬(X軸)X高(Z軸)或是寬(X軸)X高(Z軸)X深(Y軸)。

    回覆刪除