Android drawable圖檔适配
Android機型衆多,螢幕尺寸、分辨率也有很多種,如何适配各種機型也是Android的技能之一。
适配的目的:
- 提高圖檔顯示的品質
- 減少圖檔的記憶體占用
- 減少cpu性能的使用
一·先說mipmap
- Android studio在建立App項目裡,自動在res裡會建立幾個mipmap檔案夾,裡面是幾張icon圖示
- 根據Android官方的描述,mipmap僅僅用于存放APP啟動圖示,可由Image Asset Studio生成。Image Asset Studio會生成mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi五種尺寸的圖示。
- 自己使用的圖檔放在對應的drawable檔案夾裡
- 圖示最好不要随意定義尺寸,分辨率過低會模糊,過高徒增APK包大小。各種密度下的圖示建議尺寸為
密度 | 建議尺寸 |
---|---|
mdpi | 48*48 |
hdpi | 72*72 |
xhdpi | 96*96 |
xxhdpi | 144*144 |
xxxhdpi | 192*192 |
二·drawable圖檔适配
相關概念
dpi
每英寸點數,全稱dots per inch。用來表示螢幕密度,即螢幕實體區域中的像素量。高密度螢幕比低密度螢幕在給定實體區域的像素要多。
ppi:實體每英寸的像素,由硬體确定;dpi是由系統根據ppi來确定的。
dp
即dip,全稱device independent pixel。裝置獨立像素,是一種虛拟像素機關,用于以密度無關方式表示布局次元或位置,以確定在不同密度的螢幕上正常顯示UI。在160dpi的裝置上,1dp=1px。
density
裝置的邏輯密度,是dip的縮放因子。以160dpi的螢幕為基線,density=dpi/160。
getResources().getDisplayMetrics().density
sp
縮放獨立像素,全稱scale independent pixel。類似于dp,一般用于設定字型大小,可以根據使用者設定的字型大小偏好來縮放。
文字不适應dp的原因,Android可以在設定頁面設定字型的大小(型号為:小、中、大,可能還有其他型号大小,中型 1sp = 1dp),修改的就是sp
6種通用密度
Android系統為了簡化開發者為多種螢幕設計使用者界面的方式,Android将實際螢幕尺寸和範圍作了通用規定,稱作“根據可用螢幕寬度管理螢幕尺寸的新技術”。
通用密度是以mdpi(中)為基線配置的,此基線基于第一代Android裝置(T-Mobile G1)的螢幕配置。
六種通用密度為
密度 | dpi範圍 | dp與px關系(手機通用比對,不包含全部) |
---|---|---|
ldpi(低) | ~120dpi | (0.75)1dp = 0.75px |
mdpi(中) | ~160dpi | (1.0)1dp = 1px |
hdpi(高) | ~240dpi | (1.5)1dp = 1.5px |
xhdpi(超高) | ~320dpi | (2.0)1dp = 2px |
xxhdpi(超超高) | ~480dpi | (3.0)1dp = 3px |
xxxhdpi(超超超高) | ~640dpi | (4.0)1dp = 4px |
Android系統圖檔适配原則
Android為了更好地優化應用在不同螢幕密度下的使用者體驗,在項目的res目錄下可以建立drawab-[density](density為6種通用密度名)目錄,開發者在進行APP開發時,針對不同的螢幕密度,将圖檔放置于對應的drawable-[density]目錄,Android系統會依據特定的原則來查找各drawable目錄下的圖檔。查找流程為:
-
先查找和螢幕密度最比對的檔案夾。
例如,目前裝置螢幕密度dpi為160,則會優先查找drawable-mdpi目錄;如果裝置螢幕密度dpi為420,則會優先查找drawable-xxhdpi目錄。
-
如果在最比對的目錄沒有找到對應圖檔,就會向更高密度的目錄查找,直到沒有更高密度的目錄。
例如,在最比對的目錄drawable-mdpi中沒有查找到,就會查找drawable-hdpi目錄,如果還沒有查找到,就會查找drawable-xhdpi目錄,直到沒有更高密度的drawable-[density]目錄。
-
如果一直往高密度目錄均沒有查找,Android就會查找drawable-nodpi目錄。
drawable-nodpi目錄中的資源适用于所有密度的裝置,不管目前螢幕的密度如何,系統都不會縮放此目錄中的資源。
是以,對于永遠不希望系統縮放的資源,最簡單的方法就是放在此目錄中;同時,放在該目錄中的資源最好不要再放到其他drawable目錄下了,避免得到非預期的效果。
如果在drawable-nodpi目錄也沒有查找到,系統就會向比最比對目錄密度低的目錄依次查找,直到沒有更低密度的目錄。
例如,最比對目錄是xxhdpi,更高密度的目錄和nodpi目錄查找不到後,就會依次查找drawable-xhdp、drawable-hdpi、drawable-mdpi、drawable-ldpi。
圖檔适配查找流程 與 流程圖
流程
舉個例子,假如目前裝置的dpi是320,系統會優先去drawable-xhdpi目錄查找,如果找不到,會依次查找xxhdpi → xxxhdpi → hdpi → mdpi → ldpi。對于不存在的drawable-[density]目錄直接跳過,中間任一目錄查找到資源,則停止本次查找。
總結一下圖檔查找過程:優先比對最适合的圖檔→查找密度高的目錄(升序)→查找密度低的目錄(降序)。
流程圖
圖檔的縮小與放大
前述說到Android為了能夠更好地适配各種螢幕,會依據目前裝置的dpi對drawable-[density]目錄中的圖檔進行縮放,那麼什麼情況下圖檔被放大,什麼情況下圖檔被縮小呢?
圖檔的縮放會消耗一些cpu性能
- 如果圖檔所在目錄為比對目錄,則圖檔會根據裝置dpi做适當的縮放調整。
- 如果圖檔所在目錄dpi低于比對目錄,那麼該圖檔被認為是為低密度裝置需要的,現在要顯示在高密度裝置上,圖檔會被放大。
- 如果圖檔所在目錄dpi高于比對目錄,那麼該圖檔被認為是為高密度裝置需要的,現在要顯示在低密度裝置上,圖檔會被縮小。
- 如果圖檔所在目錄為drawable-nodpi,則無論裝置dpi為多少,保留原圖檔大小,不進行縮放。
縮放計算
那麼六種通用密度下的縮放倍數是多少呢?以mdpi為基線,各密度目錄下的放大倍數(即縮放因子density)如下
密度 | 放大倍數 |
---|---|
ldpi(低) | 0.75 |
mdpi(中) | 1.0 |
hdpi(高) | 1.5 |
xhdpi(超高) | 2.0 |
xxhdpi(超超高) | 3.0 |
xxxhdpi(超超超高) | 4.0 |
縮放倍數(縮放因子)計算方法:對于任意裝置,各drawable-[density]目錄下的圖檔放大倍數的計算公式
圖檔縮放後的記憶體計算
- 圖檔占用的記憶體與圖檔顯示的控件沒有關系。
- 圖檔縮小不會增加記憶體,會增加cpu的消耗。
- 圖檔放大增加記憶體,增加cpu的消耗。
- 如果圖檔顯示控件的寬高 比 加載到記憶體的圖檔寬高(縮放後的圖檔)更大,則圖檔會失真
圖檔記憶體與寬高的關系:
- 圖檔記憶體占用 = bitmap width * bitmap height * 顔色深度(機關Byte)
- 圖檔的寬高與圖檔的原始寬高、圖檔在哪個檔案夾、裝置dpi有關
- bitmap width = 原始寬高 * 裝置dpi / 圖檔所在檔案夾dpi
切圖與放的位置
關于切圖的選取,Android官方給的建議,各種密度都給出一套圖,分别放置在對應的drawable目錄下,這種适配是最好的。但也存在問題,一是這種方式會增大安裝包的大小;二是很多公司UI在出圖時隻會出一套。
在這種情況下,怎麼使用好這一套切圖呢?由于目前的Android智能手機的螢幕基本都在1080p了,螢幕的dpi多數都處于320~480,為了更好地适配,同時為了節省記憶體成本,建議将切圖放置在drawable-xxhdpi目錄,同時建議UI針對該密度的裝置設計切圖。
Android TV切圖
電視的dpi一般都較低
機頂盒切圖放置位置和手機不同
- 在TV盒子上,UI 按照給手機出切圖的方式導出的 xxhpi、xhdpi、hdpi、mdpi等切圖,不能直接放置在對應 dpi 的 drawable 目錄下。
- 比如,UI 以 1080 * 1920 為基準,導出的一比一的切圖,在手機上,對應的是 xxhdpi,因放置到手機的 drawable-xxhdpi 檔案夾中。而在機頂盒上(假設機頂盒分辨率為 1280 * 720 160dpi 或 1920 * 1080 240dpi),對應的應該是 hdpi,因放置到 drawable-hdpi 檔案夾中,機頂盒需要其他切圖,應該以 hdpi 為基準進行放大或縮小出圖。
總結:
為了适配大部分機頂盒,UI 應該按照 1920 * 1080 出圖,1920 * 1080 效果圖導出的1比1的切圖,對應的是 hdpi (而非手機開發時候的 xxhdpi)。給 drawable-xhdpi、drawable-hdpi、drawable-mdpi 的切圖。編碼時,在 value-w1280p、 value-w960p 下分别設不同的值(value-w960p 下的值可按 value-w1280p 中的值等比例縮放獲得)。