那些值得你去細細研究的Drawable適配(上)

2021-03-06 郭霖

話說前段時間我寫了一篇drawable微技術的文章,也是引起了不小的反響,因為講的東西是大家天天在使用,但卻偏偏卻沒有深入了解的知識。而本篇文章的投稿者 王月半子 表示「不服」,看完我寫的那篇之後自己也忍不住寫了一篇,我閱讀之後發現寫的挺棒,於是邀請他來公眾號上投稿。由於本篇文章內容較長,因此分為上下兩篇發表。

王月半子的博客地址:http://blog.csdn.net/wrg_20100512

Android適配的問題太多,有屏幕尺寸的適配、屏幕解析度的適配以及不同系統版本的適配。反映在代碼上,就是需要在資源文件上下功夫,主要是layout和drawable目錄下的文件,這裡主要研究一下drawable的適配。首先我們先熟悉一下基本的概念。

Android中的長度單位

px(pixel)

表示屏幕實際的像素。例如,1200×1920的屏幕在橫向有1200個像素,在縱向有1920個像素。

dpi(dot per inch)

表示屏幕密度是指每英寸上的像素點數。Android將根據不同的dpi將Android設備分成多個顯示級別。具體如下:


正如drawable目錄和mipmap目錄有ldpi、mdpi、hdpi、xhdpi、xxhdpi之分。

*這裡解釋一下mipmap和drawable的區別

在Android studio開發中,新建一個module的時候不同於Eclipse(會生成drawable、drawable-ldpi、drawable-mdpi、drawable-hxpi等等),在資源文件中會生成mipmap-hdpi、mipmap-mdpi、mipmap-xhdpi、mipmap-xxhdpi和一個drawable目錄。

對於這個問題谷歌官方有說法:

drawable/

For bitmap files (PNG, JPEG, or GIF), 9-Patch image files, and XML files that describe Drawable shapes or Drawable objects that contain multiple states (normal, pressed, or focused). 

意思是說以drawable開頭的目錄存放的文件有png、jpeg、gif格式圖片文件、.9圖片以及一些XML文件。

mipmap/

For app launcher icons. 

而以mipmap開頭的目錄存放的是App的圖標。

dp

也叫dip(density independent pixel)直譯為密度無關的像素。我們猜測如果使用了這個單位,在不同屏幕密度的設備上顯示的長度就會是相同的。那麼在屏幕上顯示圖像時都是在屏幕上填充像素點,而使用這種與密度無關的像素(我們在布局文件中使用的 dp/dip 就是與密度無關的像素)是如何轉換成像素的呢?其實在Android中,將屏幕密度為160dpi的中密度設備屏幕作為基準屏幕,在這個屏幕中,1dp=1px。其他屏幕密度的設備按照比例換算,具體如下表:

由上表不難計算1dp在hdpi設備下等於1.5px,同樣的在xxhdpi設備下1dp=3px。這裡我們從dp到px解釋了Android中不同屏幕密度之間的像素比例關係。

下面換一個角度,從px到dp的變化來說明這種比例關係。

這裡我們選擇在以mipmap開頭的目錄中設計一個icon,要求icon在屏幕中佔據相同的dp。那麼對於不同的屏幕密度(MDPI、HDPI、XHDPI、XXHDPI 和 XXXHDPI)應按照 2:3:4:6:8 的比例進行縮放。比如尺寸為48x48dp,這表示在 MDPI 的屏幕上其實際尺寸應為 48x48px,在 HDPI 的屏幕上其實際大小是 MDPI 的 1.5 倍 (72x72 px),在 XDPI 的屏幕上其實際大小是 MDPI 的 2 倍 (96x96 px),依此類推。

*圖片的描述有兩種:

1、僅僅通過寬高的像素。

2、通過圖片解析度(不同於屏幕解析度,單位英寸中所包含的像素點數)和尺寸大小。

sp(scale-independent pixels)

與dp類似,但是可以在設置裡面調節字號的時候,文字會隨之改變。當系統字號設為「普通」時,sp與px的尺寸換算和dp與px是一樣的。

屏幕尺寸、屏幕解析度、屏幕密度

屏幕尺寸

設備的物理屏幕尺寸,指屏幕的對角線的長度,單位是英寸,1 inch = 2.54 cm。比如「5寸大屏手機」,就是指對角線的尺寸,5寸×2.54釐米/寸=12.7釐米。

屏幕解析度

也叫顯示解析度,是屏幕圖像的精密度,是指屏幕或者顯示器所能顯示的像素點有多少。一般以橫向像素×縱向像素表示解析度,如1200×1920表示此屏幕在寬度方向有1200個像素,在高度方向有1920個像素。

屏幕密度

是指每英寸上的像素點數,單位是dpi(dot per inch)或者ppi(pixels per inch),數值越高顯示越細膩。屏幕密度與屏幕尺寸和屏幕解析度有關。例如在屏幕尺寸一定的條件下,屏幕解析度越高屏幕密度越大,反之越小。同理在屏幕解析度一定的條件下,屏幕尺寸越小屏幕密度越大,反之越小。

屏幕尺寸和屏幕解析度,這兩個值是可以直接得到的。屏幕密度需要我們計算得到。例如我的手機的解析度是1200×1920,屏幕尺寸是7寸的。根據屏幕尺寸、屏幕解析度和屏幕密度定義不難看出他們之間的關係如下圖:


根據勾股定理,我們得出對角線的像素數大約是2264,那麼用2264除以7就是此屏幕的密度了,計算結果是323。

*備註: 

上面的出現的0.75,1,1.5,2,3,4才是屏幕密度(density)。而120,160,240,320,480,640是屏幕密度dpi(densityDpi)。

實際密度與系統密度

實際密度就是我們自己算出來的密度,這個密度代表了屏幕真實的細膩程度,如上述例子中的323dpi就是實際密度,說明這塊屏幕每寸有323個像素。7英寸1200×1920的屏幕密度是323,5英寸1200×1920的屏幕密度是452,而相同解析度的4.5英寸屏幕密度是503。如此看來,屏幕密度將會出現很多數值,呈現嚴重的碎片化。而密度又是Android屏幕將界面進行縮放顯示的依據,那麼Android是如何適配這麼多屏幕的呢?

其實,每部Android手機屏幕都有一個初始的固定密度,這些數值是120、160、240、320、480,這些就是Android為不同設備設定的系統密度。

得到實際密度以後,一般會選擇一個最近的密度作為系統密度,系統密度是出廠預置的,如440dpi的系統密度就是和它最接近的480dpi;如果是330dpi的設備,它的系統密度就是320dpi。但是,現在很多手機不一定會選擇這些值作為系統密度,而是選擇實際的dpi作為系統密度,這就導致了很多手機的dpi也不是在這些值內。例如小米Note這樣的xxhdpi的設備他的系統密度並不是480,而是它的實際密度440。


獲取設備的上述屬性

Android系統中有個DisplayMetrics的類,通過這個類就可以得到上述的所有屬性。

DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
float density = displayMetrics.density; //屏幕密度
int densityDpi = displayMetrics.densityDpi;//屏幕密度dpi
int heightPixels = displayMetrics.heightPixels;//屏幕高度的像素
int widthPixels = displayMetrics.widthPixels;//屏幕寬度的像素
String screenResolution = widthPixels + "X" + heightPixels;
float scaledDensity = displayMetrics.scaledDensity;//字體的放大係數
float xdpi = displayMetrics.xdpi;//寬度方向上的dpi
float ydpi = displayMetrics.ydpi;//高度方向上的dpi

其中xdpi = ydpi = densityDpi.列印結果如下:


上面計算的我的設備的dpi為323。這裡系統給定的屏幕密度dpi為320。

OK,基礎的東西介紹完了,那麼回歸正題:


1. android項目中那麼多以drawable開頭的文件夾,那應用的配圖應該放在哪個文件夾之下呢?

一般的開發的話,都會做三套配圖,對應著drawable-hdpi、drawable-xhdpi、drawable-xxhdpi三個文件夾。


2. 那要是做一套呢?應該做哪一套呢?

做一套也是可以的,放在drawable-xxdpi文件夾中。


3. 為什麼做一套配圖要放在drawable-xxdpi文件夾中?

這裡先不給出答案,我在網上也看了一些說法,說是省內存,這裡暫且不置可否。


明天我們就從內存的角度去分析問題3,使用同一張圖片,放置在不同的drawable文件夾,在同一設備上運行,研究一下圖片大小及內存的佔用。

如果你有好的技術文章想和大家分享,歡迎向我的公眾號投稿,投稿具體細節請在公眾號主頁點擊「投稿」菜單查看。

相關焦點

  • Android 這些 Drawable 你都會用嗎?
    當位圖像素與屏幕像素不匹配(如 ARGB_8888 的位圖顯示在 RGB_565 的屏幕上)時,防止圖片失真,建議開啟filter是否啟用位圖過濾。開啟後,當圖片進行拉伸或者壓縮時,能夠進行平滑過渡gravity當位圖尺寸小於容器尺寸時在容器中的擺放位置mipMap啟用或停用 mipmap 提示,默認為 falsetileMode平鋪模式。
  • Android 10 適配攻略,你適配了嗎?
    hl=zh_cn所以在Android 10上即使你擁有了儲存空間的讀寫權限,也無法保證可以正常的進行文件的讀寫操作。適配最簡單粗暴的方法就是在AndroidManifest.xml中添加 android:requestLegacyExternalStorage="true"來請求使用舊的存儲模式。
  • Android SVG使用之AnimatedVectorDrawable
    A指令格式elliptical Arc (A RX,RY,XROTATION,large-arc-flag,sweep-flag,X,Y)  RX,RY  所在橢圓水平方向上的半徑,垂直方向上的半徑;RX 和 RY 設置為相同的值,將得到一個圓形的弧線  XROTATION
  • 這篇文章來教你
    API21)才開始支持的,所以這個地方我們還需要適配下。如果不適配,你的最小minSdkVersion版本又小於21,則會自動在每個drawable目錄下生成對應的png圖片,反而會使apk包變大,所以這裡一定要注意了。
  • 重慶這些步道值得你我停下來細細品味
    我們所熟悉的這座城市,其實有不少值得細細品味的風景,只因你我太過匆忙,沒有發現。重慶這些步道,值得你我停下來細細品味。 山城第三步道 步道特色:保留了老重慶的風貌,觀景臺可以一覽渝中半島美景。
  • 帕斯卡契約:充滿了魅力,是一款值得沉下心來細細品味的遊戲!
    再看看官方態度,為了適配更多機型而冒著被玩家噴的風險而延期。再看到那些獲取了測試資格用著老年機而依然流暢的玩家測評,對這個遊戲的品質又上升到新的高度。5月最期待的3d魔幻大作,不管是買斷制還是聯網付費解鎖制都可以接受。5月給你5星期待,希望能如期呈現!
  • Android開發在路上:少去踩坑,多走捷徑
    Android 1.5、1.6、2.0、2.1和小屏幕的屬於古董級別的機器,市場存量也很少,新出的機器都是4.0以上的了,所以必要時需要捨棄對古董的支持,因為適配成本很高,對於新開發的應用,這個適配不值得投入。3.目前, 開發Android APP時,適應多個解析度的技術方案有哪些?
  • 值得你細細品味的幾本甜寵軍婚文,女主不小白,智商在線
    非常感謝你們在百忙之中看我的推薦,真的是榮幸之至,我一定不會辜負大家對我的期望,我會經常分享那些我認為好看的小說推薦給大家,希望親愛的你們可以喜歡。今天就給你們推薦值得你細細品味的幾本甜寵軍婚文,女主不小白,智商在線,書荒必備的好乾糧,熬夜也要看的。
  • 去內蒙,不可錯過的烤串,每一種都值得細細品味
    廣義上的烤串,也就是說燒烤的食物不分大小,烤全羊、烤羊腿這些也算是烤串,狹義上來說,烤串一般指分量比較小的食物。但是內蒙人大概是不分這麼多的,很多的內蒙人,一頓飯兩三個雞腿或者一斤多肉不再話下,對於南方或者沿海地區的人們來說,內蒙人的胃口足夠讓人瞠目結舌,當然能吃下一頭烤全羊的人還是不太可能有的。
  • 適配型濾網去甲醛性能相對較差
    日前,河北省環保產品質量監督檢驗研究院(以下簡稱河北省環保院)針對家用空氣淨化器用適配型濾網質量展開了調查,結果令人堪憂。看來,僅有空氣淨化器還不能讓人高枕無憂,必須選擇一款高質量的濾網才能真正確保空氣環境質量。
  • 這些APP說自己已經適配iPhone X了?我一個白眼翻上天去
    對於iPhone一張臉用了三年這件事,最開心的大概就是那些手機APP設計者,畢竟一個模板可以用三年以上,並且不用再為那些長短不一的屏幕去不斷的更改自己的設計方案,簡直是一勞永逸。就適配速度而言,B站絕對算得上是國內眾APP中的第一梯隊,在iPhone X發售後的第三天便完成了更新,但是現在兩周時間過去,之前那些沒解決的問題也依然還沒解決。
  • 把世間萬象拿來適配,卻不及你的美好
    「世間美景不及你,多彩多姿都是你的配色」海外粉絲在適配性上的審美還是超級高的,世間萬象景色都可以拿來適配,真是拿捏得恰到好處,適配出一切的美好!「動漫世界裡的主人公,你是整部動漫的靈魂」都說王一博是最符合撕漫男的,一個自帶漫畫濾鏡的容顏,總會在看到你的圖片的一瞬間,感覺你就是動漫中那個帶給我們無限能量的那個主人公一般,緩緩走來,甚至帶給我們無盡的靈魂擺渡人,讓心靈精神上帶來慰藉!
  • 【移動適配】移動Web怎麼做屏幕適配(一)
    說白了就是同一套代碼在不同解析度的手機上跑時,頁面元素間的間距,留白,以及圖片大小會隨著變化,在比例上跟設計稿一致。圖1.  260*400的屏幕圖片應該保持正方形,而且兩張圖之間的邊距應該隨屏幕變化而變化明白了,所以padding,margin,圖片等的大小基本都要做適配關鍵要找到一種長度單位,使得一樣的取值,在不同尺寸的屏幕上的大小按比例縮放。
  • PS2記憶棒需要適配卡才能用在PS3上
    根據官方網站的說法,PS2上的記憶棒可以用在PS3上,但是必須使用1個適配卡才能讓PS2記憶棒用在PS3上。根據PS3官方網站的FAQ:「為了使用存儲在PS2記憶棒上的遊戲進度數據,你必須拷貝數據到PS3硬碟的1個虛擬快閃記憶體卡當中,這需要1個PS2/PS1記憶棒適配卡來拷貝數據。」
  • 值得拜讀的愛情短句,句句精美走心,值得細細品味
    4.打破緘默沉靜,到達國際的盡頭,剛強的,有莊嚴的活著,為了自己的抱負和追求,敢於解開捆住四肢的脆弱和無知,趕開窩囊,活出你的精彩,活出你剛強的人生,肯定不是苛求,剛強的活著現已成為一種習慣,而且要鍥而不捨。5.放心吧,現在你所放不下的人和事,歲月會替你輕描淡寫。
  • 像素,解析度和適配
    那麼我希望我的這篇文章可以幫你解決這個困惑。我覺得很多設計師沒有搞懂解析度和像素的原因是因為沒有弄明白什麼是英寸。我們小時候家裡的電視機會說21寸大彩電,25寸大彩電,29寸大彩電等。包括手機我們也會說4.7英寸,5.0英寸等。但是顯示屏畢竟是一個面,而你用英寸來表示一個面,所以在很多人心中會把英寸誤以為是一個面積單位,也就是說把英寸看成了是平方英寸。
  • Android解析度適配寶典
    有些知識你學到了,你的朋友不一定學到,那就趕快分享給TA吧!!
  • 星太奇:田姬同學的作文值得讓人細細品味,古老師卻一秒變了臉色
    星太奇:田姬同學的作文值得讓人細細品味,古老師卻一秒變了臉色上回說到奮豆同學仗著自己手臂上有兩條槓,徹底展示了什麼叫走路都可以橫著走,不但濫用自己的權利插隊,還給自己找了冠冕堂皇的藉口,至於小桂子為什麼會在操場撿到奮豆的兩條槓,無疑就是跑去上女廁所了,而對奮豆了如指掌的星太奇一眼就認出了這是奮豆的東西
  • 微生物所鏈黴菌次級代謝產物產量的適配策略研究獲進展
    微生物所鏈黴菌次級代謝產物產量的適配策略研究獲進展 2017-12-04 微生物研究所 【字體  近日,微生物生理代謝研究組利用以上元件研究發現,次級代謝產物的合成時序與鏈黴菌前體供應等生理狀態不匹配是制約產量提高的重要原因之一。為解決這一問題,該研究組利用鏈黴菌時序啟動子,建立優化、適配次級代謝產物生物合成的全新自調控策略。