Screen size
是指device真正的物理尺寸,例如對角線長度為五寸的手機,其screen size就是5寸。Android api把物理尺寸分成四個等級: small, normal, large, extra-large。不過在API 13以上,這個等級就已經deprecated,詳見Android文件。每個等級有定義出最小的虛擬解析度(螢幕上能夠表現出的dp總數):
xlarge >= 960dp x 720dp
large >= 640dp x 480dp
normal >= 470dp x 320dp
small >= 426dp x 320dp
Screen density
螢幕密度是指螢幕在某個物理尺寸內所能表現的pixel數量,所以是密度的概念,通常稱為dpi (dots per inch)。 Android把螢幕密度分成五個等級:low, medium, high, extra-high, extra-extra-high, extra-extra-extra-high。 (Google工程師真的有比較聰明嗎?看這命名...)Resolution
解析度通常會跟螢幕密度搞混了,這是指一個螢幕「所有」能表現的pixel數目,是總量的概念,不是密度的概念,通常程式中不會直接面對resolutoin。Density-independent pixel (dp)
這是一個虛擬的pixel單位,讓我們定義UI的時候,不用去考慮螢幕密度的問題。1dp相當於medium screen density (160dpi)時的一個pixel大小 (白話文就是 當你的螢幕每一英吋能表現160個pixel的時候,這時候一個pixel就可以稱為1dp)。Android runtime會自動做縮放補償,例如一個長度為1dp的image,如果在mdpi的螢幕上,那就剛好用一個pixel表現,但是如果在240dpi的螢幕上,就需要用 (240/160) * 1dp = 1.5個pixel來「補償」放大原本1pixel的區域。知道了以上的名詞定義,我們可以簡單列出兩個螢幕之間的關係:
如果螢幕A和螢幕B有相同解析度,而且螢幕A的尺寸比螢幕B大的話,那按照定義螢幕A的dpi值一定小於螢幕B的dpi值,這是簡單的數學,也可以說螢幕A的一個pixel的物理尺寸是大於螢幕B的一個pixel的物理尺寸。
如果只用pixel當UI單位的話有什麼問題?
如果用pixel當單位的話,就會在不同的density螢幕中看到依照兩者density的倍數縮放的widget,這會造成widget在較低的dpi螢幕上的物理尺寸變大,而在較高dpi螢幕上物理尺寸較小。舉例來說,一張160 pixel x 160 pixel的影像,在160dpi我們看到的實際尺寸是1 inch x 1 inch,但是在420dpi的螢幕上,1 inch相當於420個pixel的寬度,所以160個pixel的長度會變成 160/420 inch,反之在較低dpi螢幕上(例如80dpi)會變成看到160/80 inch的長度。有時候這不會不好,如果兩者的解析度一樣的話就只是等比例縮放而已,但是通常解析度不會一樣,這時候dpi的差距常會造成usability的問題,例如按鈕變得太小按不到,或是widget變得太大超出螢幕範圍。
如何達成在各種screen density螢幕中正確表現?
由上可知,在UI中使用dp當作單位的好處就是,在不同的density螢幕中,android runtime會把這個因為單一pixel物理尺寸不同所造成的widget膨脹或縮減作物理尺寸的補償,這會讓使用者看到近似的物理尺寸的widget。不過這還是會造成一些問題,如果在大螢幕(例如tablet)上的UI用了實際尺寸較大的widget,到小螢幕時還是會一樣大! 所以如果螢幕大小差距太大時,兩者需要不同的layout file,不能依賴android runtime縮放來保證usability。另外一個問題是android runtime自動放大補償的時候,圖像品質就會下降。
所幸android支援alternative configuration給不同的density不同的bitmaps/layout,也就是我們常會在layout和drawables目錄下看到各種xhdpi, xxhdpi目錄的原因。不過現在已經改成要用sw<N>dp configuration qualifier了,之前講的screen size定義在API level 13以後都deprecated。
沒有留言:
張貼留言