在開發(fā)過(guò)程中,我們總是需要考慮如何適配各種的屏幕。但是你有沒(méi)有想過(guò),我們?yōu)槭裁葱枰m配屏幕呢?為什么需要那么多屏幕適配方案呢?
重新認(rèn)識(shí)像素
你一定聽說(shuō)過(guò)像素,它是顯示的基本單位。我們使用的px就表示像素。那這里有一個(gè)問(wèn)題,如果我們用像素表示UI的大小,10px在任何屏幕都表示10個(gè)像素點(diǎn),這樣不就行了嗎?為什么還要適配不同屏幕呢?
這是因?yàn)橄袼攸c(diǎn)沒(méi)有物理大小,簡(jiǎn)單的說(shuō)就是1cm屏幕可以有10像素,也可以有100像素。一般我們用 ppi 來(lái)表示每英寸有多少像素。
如下圖,如果用像素來(lái)適配,相同大小的屏幕每單位長(zhǎng)度的像素個(gè)數(shù)不同時(shí),就會(huì)造成大小不同的問(wèn)題。

那為什么像素不固定大小呢?因?yàn)椴煌钠聊恍枨蟛煌?,比如手機(jī)和筆記本分辨率都有 1080 * 1920分辨率的,但是手機(jī)和筆記本的屏幕尺寸不同,如果需要讓手機(jī)分辨率提高,就必須讓手機(jī)屏幕的像素點(diǎn)比筆記本的小。
提到 PPI(pixels per inch),就不得不提 DPI(dots per inch)。從英文名看出,PPI是指每英寸像素;而 DPI是指每英寸墨點(diǎn),它最早用于打印行業(yè),后來(lái)引申到計(jì)算機(jī),就是 PPI的概念。目前 PPI和 DPI是經(jīng)常混用,可以認(rèn)為它們是一個(gè)東西。具體可以看stackoverflow的這篇 What is the difference between ppi vs dpi?回答。
使用密度無(wú)關(guān)像素
上面我們提到,由于單位長(zhǎng)度的像素點(diǎn)的個(gè)數(shù)不同,導(dǎo)致使用像素點(diǎn)適配屏幕是不可行的。這時(shí)候我們就會(huì)想,如果系統(tǒng)自動(dòng)幫我們適配這個(gè)單位長(zhǎng)度像素個(gè)數(shù)的差異不就行了嗎?
在 Android中,Google提供了 dp(density- independent pixel,即密度無(wú)關(guān)像素,也叫dip)來(lái)實(shí)現(xiàn)這個(gè)功能; 在ios中,則是使用 pt(獨(dú)立像素)。注意:這兩者是一個(gè)意思,只是叫法不同。
假設(shè)我們繪制一個(gè)3dp * 3dp的正方形,在1PPI的屏幕中,該正方形的大小為 3px * 3px;而在2PPI的屏幕中,正方形的大小就變成了 6px * 6px。效果如下圖,我們可以看到,使用dp后在不同的PPI的屏幕上表現(xiàn)是一致的。

上述的方案完美解決了PPI的問(wèn)題,但是這樣就可以適配所有屏幕了嗎?答案當(dāng)然是不行,因?yàn)?strong>設(shè)計(jì)稿的大小是固定的。一般設(shè)計(jì)給的設(shè)計(jì)稿都是360dp * 640dp的,但是實(shí)際上的屏幕尺寸可不止這些。像 Android One機(jī)型是
320dp * 569dp;而Google Pixel 機(jī)型則是 411dp * 731dp。
假設(shè)我們需要實(shí)現(xiàn)一個(gè)發(fā)送消息的UI(一個(gè)輸入框和一個(gè)發(fā)送按鈕),如果按照設(shè)計(jì)稿擺放UI,在與設(shè)計(jì)稿dp大小相同的機(jī)型上是正常的,但是在不同dp大小的機(jī)型上,表現(xiàn)就有問(wèn)題了。如下圖,如果屏幕dp大小小于設(shè)計(jì)稿(這里為 320dp * 569dp),則發(fā)送的按鈕顯示不完全;如果屏幕dp大小大于設(shè)計(jì)稿(這里為 411dp * 731dp),則會(huì)空出多余的空間。這也是為什么在Android的界面開發(fā)中,我們一般需要設(shè)置一個(gè)最大寬度和最小寬度的原因。

使用比例
上面說(shuō)到,即使把UI控件適配成大小相同,在屏幕大小不同的情況下,也會(huì)出現(xiàn)UI控件顯示不完全或者顯示占比與設(shè)計(jì)稿不同的問(wèn)題。
既然把UI控件適配成大小相同沒(méi)有用,那么我們干脆按照UI控件占屏幕大小的比例來(lái)適配。有兩種做法,一種是按照雙邊(長(zhǎng)和寬)的比例來(lái)適配;一種是按照單邊(長(zhǎng)或者寬)的比例來(lái)適配。
雙邊適配
這里還是以上面的發(fā)送消息的UI為例。從圖中,我們知道,輸入框的長(zhǎng)占比為 13/20,寬占比為 1/18;發(fā)送按鈕長(zhǎng)占比為 1/5,寬占比為 1/18.通過(guò)相同的比例換算,效果如下圖所示:

按照比例的方案看上去解決了問(wèn)題。但是這要在長(zhǎng)寬比固定(這里是16:9)的情況下才有效。如果是在長(zhǎng)寬比不同的屏幕上,如 16:9 的屏幕和 20:9 的屏幕上繪制正方形和圓形,則會(huì)出現(xiàn)拉伸的問(wèn)題。效果如下圖:

單邊適配
既然雙邊適配不行,那就以占寬的比例來(lái)適配,UI的高則按照設(shè)計(jì)稿的比例乘以當(dāng)前的UI的寬來(lái)獲得。這樣就既能保證UI控件的寬,同時(shí)UI控件的長(zhǎng)寬比例不變。以高的比例來(lái)適配與寬的比例類似,下面就不贅述了。

如上圖所示,使用單邊適配時(shí),在屏幕寬度不同的情況下,能按照當(dāng)前屏幕寬度對(duì)UI控件進(jìn)行縮放;在屏幕比例不同的情況下,能根據(jù)設(shè)計(jì)稿的比例來(lái)計(jì)算出當(dāng)前屏幕下的UI控件的高度。
看上去適配單邊是一個(gè)完美的方案。但是如果你想要顯示全屏,這個(gè)方案就不行了。如下圖所示,使用單邊適配在不同屏幕上的效果。

仔細(xì)看的話,我們會(huì)發(fā)現(xiàn)上圖那種情況如果是使用雙邊適配,那就是沒(méi)有問(wèn)題。從中我們可以發(fā)現(xiàn),其實(shí)適配方案是需要根據(jù)自己的需求來(lái)選擇的,這也是為什么有這么多適配方案的原因。
總結(jié)
前文詳細(xì)介紹了以像素、密度無(wú)關(guān)像素、比例適配的不足,同時(shí)解釋了為什么我們要考慮屏幕適配以及適配方案多種多樣的原因。
需要注意的是上面只討論了手機(jī)的屏幕,實(shí)際上現(xiàn)實(shí)中還有平板、筆記本、智能手表、電視等等。完善的屏幕適配遠(yuǎn)比我們想象的要復(fù)雜。工作中,我們不需要考慮那么多,只需要根據(jù)自己的需求來(lái)選擇的合適的適配方案就行了。