開篇
近日,在研究屏幕適配的問題,由于涉及比較多概念,例如ppi、dpi、dip、px等等,在適配屏幕的時候經(jīng)常不得要領(lǐng),寫此文章,做個總結(jié)。
相關(guān)名詞
屏幕尺寸: 也就是我們平時所說的某某手機是幾寸屏, 比如HTC one V這款手機是3.7寸的, 這里的寸說的是英寸(inch),國際上習(xí)慣使用的單位,1inch = 2.54cm,3.7寸指的是屏幕的對角線的長度。
屏幕分辨率: 指屏幕的寬和高的像素數(shù), 比如HTC one V是480x800的。
屏幕密度: 每英寸的像素數(shù),比如HTC one V, 是252 px/inch。
px: 像素。一塊顯示屏是由很多的光點組成的,每一個光點就是一個像素。由于這些光點很小很密,想想看,在上面提到的3.7寸的手機上,橫向有480個光點,縱向有800個光點,所以顯示出來的文字或者圖片才很細(xì)膩平滑。
ppi: 和屏幕密度一個意思, 全稱是pixel per inch. 是專業(yè)一點的叫法。
dpi: dot per inch,每英寸的點數(shù)。在電子顯示范疇內(nèi)它和PPI是一個意思。 只有在打印時這個縮寫才有意義,在打印領(lǐng)域不存在 PPI的叫法,只說DPI,它表示打印機每英寸打印幾個像素點。寬高同樣像素下,dpi越大,打印出來的圖案越小。
dip: 或者叫dp,這是開發(fā)中特有的一種度量,稱作屏幕無關(guān)像素, 它不表示任何具體的長度或者像素點, 這個值只有在 具體屏幕密度的手機上,才會被轉(zhuǎn)換為具體的像素值。 這個時候才會有實際意義。
dip在屏幕中顯示
首先看圖:
首先,假設(shè)我們需要設(shè)計一個屏幕寬的控件而不使用match_parent在這個參數(shù),在一個1280x720像素,5英寸的屏幕中,我們可以計算出該屏幕的dpi(ppi)=(12802+7202)^0.5 / 5 = 1468.60 / 5 = 293.72 , 根據(jù)上表可知:240dpi<293.72dpi<320dpi,所以該屏幕對應(yīng)的主流像素密度xhdpi,此時由圖2我們可知,在該屏幕設(shè)計1dip的長度,其實際尺寸應(yīng)為2px。此時,需要設(shè)計一個控件其寬為屏幕寬(720px),我們就可以將其width設(shè)置為720 / 2 = 360dip。
看到這里,你或許會有疑問:在不同屏幕尺寸,設(shè)計一個占據(jù)屏幕寬的控件,難道都需要這么麻煩嗎?也不一定是。
我們再舉一個常見的屏幕尺寸:1920x1080像素,5.5英寸的屏幕。通過計算得出dpi=400.53,屬于xxhdpi。當(dāng)我們設(shè)置360dip時,屏幕的實際像素為540px剛好為屏幕的一半1080px。
那么,是否能得出360dip就是屏幕的寬呢?答案當(dāng)然是否定的,對于目前主流的屏幕分辨率例如1280x720像素5英寸(xhdpi),1920x1080像素5.5英寸(xxhdpi),360dip經(jīng)過計算得出恰好占據(jù)屏幕。但當(dāng)碰上某些奇葩屏幕分辨率時例如:1280x768像素,5寸(xhdpi)、1920x1152像素,5寸(xxhdpi),此時360dip分別對應(yīng)720px與1080px,此時顯然達(dá)不到屏幕的寬。
由此我們可以得出結(jié)論,對于一些主流像素,主流屏幕尺寸,參考xxx手機,適配這些屏幕時,用dip(dp)就能滿足我們的需要,但是對于市面上的奇葩分辨率及尺寸,我們得用其它手段適配屏幕(例如:采用百分比的方式適配)。
圖片在屏幕中的顯示
首先查看這副圖片:
我們可以舉個例子:
當(dāng)我們把一套適配1280x720像素的切圖放在xhdpi的drawable文件夾下(其它drawable文件夾沒有圖片),一個xxhdpi的設(shè)備在布局文件中引用了某個切圖,假設(shè)這個切圖的寬占據(jù)了360px(1280x720像素屏幕的一半),由于xxhdpi設(shè)備獲取到的圖片在xhdpi下,故系統(tǒng)會自動放大該圖片為360px * 1.5 = 540px,此圖片剛好占據(jù)此xxhpi設(shè)備屏幕的一半。同理反過來,一套1920x1080像素的切圖同樣可以適配xhdpi的屏幕。
但是,需要注意的是,如果要適配例如800x480像素的屏幕,這張圖片的顯示是達(dá)不到我們的預(yù)期的。可以舉市面上的854x480像素的機型,這些機型往往在4寸到4.5寸之間,通過計算得出ppi在207.3~233.2之間,同屬于hdpi。當(dāng)該機型的某個控件引用了此圖片(控件是自適應(yīng)圖片大小),可以通過計算得出實際占據(jù)屏幕的像素為:360px * 3/4 =270px。很顯然,該圖片已經(jīng)超出屏幕的一半以上了。這種情況最好的解決辦法還是增加相應(yīng)的布局。
適配主流屏幕
我們查看2016年11月與12月的設(shè)備分辨率(友盟統(tǒng)計):
由統(tǒng)計我們可知:目前主要的屏幕寬的像素為720p、1080p、480p以及540p,如果需要適配主流屏幕,那么我們需要做的就是適配320dp的屏幕以及360dp的屏幕,對于這種差異,我們可以在layout-w320dp文件夾下創(chuàng)建相應(yīng)的文件即可。當(dāng)然由于w320dp主要對應(yīng)市面上480 * 800的機型,其屏幕比例為3:5,對于高度方向的差異也很明顯,如果整個界面是獨占式,無法上下滾動,那么我們還需要對高度方向進(jìn)行相應(yīng)的調(diào)整。
同樣,有些平板分辨率則是1920*1200(7英寸),屬于xhdpi,但是360dp的寬在屏幕上的只占據(jù)720px,顯然360dp并不是所有機型的屏幕寬。
如果你的app只針對主流機型的屏幕適配(屏幕寬為360dp,屏幕比例為16:9),那你大可不必創(chuàng)建多種布局文件去適配,但是如果你的目標(biāo)不僅僅是主流機型,那么就一定需要適配。
需要幾套切圖
對于現(xiàn)在屏幕設(shè)計需要給幾套切圖,看了大多數(shù)博客,總結(jié)出的結(jié)果是:可以僅給出一套720 * 1280 的圖片,放在drawable-xhdpi的資源文件夾下。由于低dpi的設(shè)備讀取高dpi文件夾的屏幕會按比例縮小,高dpi的設(shè)備讀取低dpi文件夾的屏幕會按比例變大,看到這也許你會擔(dān)心:如果低dpi的設(shè)備讀取這些高dpi文件夾下的圖片會增加內(nèi)存消耗嗎?筆者起先也有疑惑,首先將圖片按3:4:8的比例分別放置在drawable-hdpi、drawable-xhdpi、drawable-xxhdpi文件夾下,圖片的寬高也按3:4:8的比例縮放,我們長寬分別為:27x27:36x36:54x54。我們使用下面這個方法將代碼讀取到內(nèi)存中:
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image_test);
int byteCount = bitmap.getByteCount();
Log.d("MainActivity", "byteCount: " + byteCount);
我們用xhdpi屏幕機型去執(zhí)行這段代碼,分為三種情況:
- 不刪除圖片
- 刪除drawable-xhdpi文件夾下圖片
- 繼續(xù)刪除drawable-xxhdpi文件夾下圖片
最后讀取的byteCount都為:5184(36*36*4、54*2/3*54*2/3*4、27*4/3*27*4/3*4)
由此我們可以總結(jié)出,一套圖片放置在相應(yīng)文件夾下,低dpi的設(shè)備讀取高dpi文件夾的圖片不會導(dǎo)致內(nèi)存消耗,但是如果你把本該放在drawable-xhdpi圖片放在drawable-hdpi文件夾下,那么將會消耗更多內(nèi)存,甚至?xí)?dǎo)致ImageView中顯示的圖片變大;如果反過來呢,本該放在drawable-xhdpi圖片放在drawable-xxhdpi文件夾下,那么就會加載的圖片比實際預(yù)期尺寸要小。
這樣做會使得xxhdpi的屏幕讀取到的圖片效果沒有基于1080p設(shè)計的效果好,所以有的博主推薦基于1080p的設(shè)計,但是這樣也會使得apk的空間變大,這當(dāng)然也不是好事,魚和熊掌不可兼得,所以還是需要看實際情況再選擇哪套圖設(shè)計。
總結(jié)
360dp寬是目前主流機型的屏幕寬,但不是絕對的,對于一些奇葩分辨率的屏幕以及平板則不適用。
320dp寬是以前主流機型的屏幕寬,同樣也不是絕對的,目前市面上同樣有該種屏幕的機型,占據(jù)比例大概在3.5%,如果要作主流機型適配同樣不能忽略。
一套720p或者1080p的切圖足以應(yīng)對主流機型的屏幕適配問題,且低dpi的屏幕讀取高dpi文件夾下的圖片,由于會自動縮小相應(yīng)比例,所以內(nèi)存不會比讀取相同dpi文件下的圖片更耗內(nèi)存。
感謝以下文章的參考:
http://www.android100.org/html/201505/24/149342.html
http://blog.csdn.net/xiebudong/article/details/37040263/
http://www.cocoachina.com/android/20151030/13971.html