深入理解Android的密度獨立性

前言

安卓是一個只對硬件設備限制有很少限制的移動操作系統。生產商們幾乎可以創造任何形狀的、尺寸的和密度的屏幕的設備。設備可以有物理鍵盤和按鈕或者只有虛 擬鍵盤和按鈕。由於它的設備客製化的自由性給軟件開發者們製造了一些麻煩。首先,應用軟件怎樣在各種各樣的設備上保證一致的用戶體驗呢?其次,應用軟件怎 樣利用一些擁有高端硬件或者獨特特性的設備的優勢呢?安卓在當初研發的時候就考慮了這些,給開發者提供了一些工具去支持各種配置的設備,優化了不同配置的 設備的用戶體驗,這些將在下面介紹。

爲了應用程序的靈活性和兼容任何配置的設備,認真思考合適的跨配置的用戶體驗是必須的。創建一個Android應用程序時,設計者和開發者必須創建一個無 論是在小尺寸的手機上還是在大尺寸的平板上都能運行良好的UI界面。他們還要考慮圖片資源對高密度和低密度的屏幕的優化。這篇BLOG的中心就是安卓怎樣 支持不同密度的屏幕。

安卓的基本設計思想就是保證用戶界面中的元素擁有相同的物理大小,而不論屏幕的密度。爲什麼呢?很簡單,無論什麼樣的屏幕密度一個用戶的手指的物理尺寸是 不變的。按鍵或者可以按的元素在任何設備上應該渲染成和手指物理大小一樣尺寸(比手指印大一點)。文本和字母在不同的設備上也應該渲染成一樣的字體大小 (可讀的)。

 

屏幕密度不等於分辨率

屏幕像素密度是分辨率和顯示尺寸的比值,可以用每英寸像素點或者dpi來度量。dpi越高,每個像素點越小也就越清晰。簡單地說,dpi越高就意味着每英 寸顯示的細節越多,而不是直接取決於高分辨。舉個例子,Galaxy Nexus(對角線 4.65'')分辨率爲:720x1280,Nexus 7(對角線 7'')分辨率爲:800x1280.常見的錯誤觀點是認爲他們擁有相同的屏幕像素密度,因爲它們的分辨率幾乎一樣。然而,Galaxy Nexus 的屏幕像素密度約爲316dpi,Nexus 7的屏幕像素密度爲216dpi,相差甚遠。這是因爲雖然它們擁有一樣的分辨率,但是它們顯示尺寸卻不一樣。再次說明,屏幕像素密度是分辨率和顯示尺寸的 比值,兩個因素一起決定屏幕像素密度。

 

密度級別

無數的Android設備的像數密度各不相同,分佈爲100dpi到480dpi以上。爲那些不同密度的屏幕優化圖片,就必須創建不同分辨率的圖片。然 而,嘗試爲所有的像數密度優化所有的圖片資源將會使是讓人無法想象的無聊乏味,同時引起應用程序大小變的臃腫,簡單的方法是不可行的。作爲折衷方 案,Android用密度級別的概念把擁有確定密度範圍的設備分類。這樣應用程序只需要針對每個密度級別來優化圖片,而不是針對所有可能的像素密度來優 化。這使得設計者和開發者的工作負擔是合理的,時阻止了應用程序大小的膨脹。當然,代價就是:不同像素密度的設備上圖片渲染後的物理尺寸是大小不一的,這 點將會在後面介紹。

 

因此,設計者和開發者如何根據密度塊來優化圖片資源?首先,要決定的是圖片的呈現尺寸。例如,一個圖標試圖在屏幕中呈現  0.5x0.5的大小。下一步,創建一個圖片支持的最大密度,或者是一個可伸縮的矢量圖。最好的做法是支持最大的密度,當前是在xxhdpi 就在480dpi.在480dpi,一張0.5x0.5的圖片轉換爲240x240px.一旦圖形資源的最大密度版本被創建在240x240px.那麼它 就可以在隨後創建的密度塊版本被適當的縮小比例,每個版本用相同的文件名。Google建議不要在213dpi創建tvdpi版本,因爲它僅僅是被特定的 應用程序所需要,並且被一小撮設備而使用。一旦所有的版本被創建,它們可以被添加到drawable文件夾,並且用資源標識符告訴Android系統每一 種密度塊所需要的大小。最後,參考一下在xml佈局層的圖形資源,然後通過編碼它們的名稱在R文件中生成,R文件是一個可以在程序中引用所有資源的文件。 Android系統會在運行時加載資源,並盡它最大的努力去匹配實際的設備配置與資源標識符應用。假如任何圖片資源的密度版本沒有被包括在 內,Android將用另外的密度版本並且將它縮小到所需要的合適的尺寸大小。當然,不推薦讓Android系統來這樣做。因爲Andorid系統在操作 圖片資源時並沒有圖片編輯軟件操作的更加有 效和精確。

 

尺寸單位

在安卓中,用戶界面可以在xml文件中創建或在在代碼中實現。有幾種單位可以用來表示一個表單的長寬。它們可以用在很多元素上來設定寬、高、外間距、內間距等等。

px——屏幕上真實的像素。這是一個與像素密度有關聯的單位,一px單位的物理大小取決於屏幕的像素密度。

in——屏幕上的物理英寸。這是一個與像素密度無關聯的單位,一in單位的物理大小在任何像素密度的屏幕上都是一樣大的。一in單位轉化爲多少px單位取決於屏幕的像素密度。

mm——屏幕上的物理毫米。這是一個與像素密度無關聯的單位,一mm單位的物理大小在任何像素密度的屏幕上都是一樣大的。25.4mm等於一in。mm單位轉化爲多少px單位取決於屏幕的像素密度。

pt——點,屏幕上普通字體大小單位。這是一個與像素密度無關聯的單位,一pt單位的物理大小在任何像素密度的屏幕上都是一樣大的。72pt等於一in。一pt單位轉化爲多少px單位取決於屏幕的像素密度。

dp——像素密度無關聯的像素單位。這是一個與像素密度無關聯的單位。然而一dp單位的物理大小在不同的像素密度屏幕上只是近視的相等。大約160dp等於一in。在一dp轉化爲160dpi中的一個比例因子是與設備的密度級別相關聯的。一dp等於多少像素取決於屏幕的像素密度和設備所屬的密度級別。

sp——大小獨立的像素單位,特地指定text的大小。這是一個與像素密度無關聯的單位。然而一sp單位的物理大小在不同的像素密度屏幕上只是近視的相等。在一sp轉化爲160dpi中的一個比例因子是與設備的密度級別以及字體表現的大小相關聯的。一sp等於多少像素取決於屏幕的像素密度和設備所屬的密度級別。

 

http://static.oschina.net/uploads/img/201304/23112447_8Zj2.png
 

 

神奇的“dp”

如前面討論的那樣,"px"不是密度獨立的,並且在不同的設備上擁有不同的大小,然而"in","mm"和"pt"是密度獨立的,當然在不同的設備上擁有相同的大小。但是,"dp"和"sp"跟其餘的有一些不同,雖然他們是密度獨立的,但是他們在 不同的設備上擁有不同的大小。這是爲什麼呢?答案是"dp"和"sp"是如何被計算成像素的。Android使用mdpi(160dpi)作爲其標準密 度,這裏 1dp就是1px。本質上來講,"dp"可以被認爲是在160 dpi上的“px”。這就是爲什麼160 dp轉換爲大約1 in。因此根據設備密度等級與標準的密度(mdpi)之間的比率來轉換"dp"到"px"。

"dp"趨向於不同的物理大小的原因是由於相同的縮放因子被應用到整個密度桶。該縮放因子是計算密度桶dpi,而不是設備真實的 dpi。當設備的dpi不完全地與它的密度桶dpi相同的時候,相同數目的"dp"轉換爲相同量的"px"。這就會導致相同數目的"px"被顯示到不同密 度的屏幕上,以不同的大小呈現出來。

上面的表格顯示了100 dp如何在不同密度的設備上轉換爲"px"。100 dp應該大致地轉化爲0.625 in,並且完美地轉換爲bucket sizes。但是,當設備的dpi少於密度桶的dpi的時候,它的像素在物理上會更大,並且相同數目的"dp"會渲染得更大,反之亦然。

因此這就引出一個問題,爲什麼"dp"允許這種物理尺寸的變化?從根本上來說,android在物理尺寸上會犧牲一些精確度,目的是爲了保持性能和顯示質 量。由於利用android的密度桶比率(0.75:1.0:1.5:2.0:3.0)讓"dp"縮放到"px",這就允許有極小的"px"舍入和簡單的 估計。同時,由於縮放因子與密度桶比率成比例,“dp”會按比例顯示爲各種密度提供的圖片資源。最後,當縮放圖行的時候,最好保持接近整數和簡單的分數,因爲複雜的分數會導致圖片顏色過渡異常和走樣。

 

定義UI元素的界限

當定義用戶界面元素的長寬時有幾個特別的選項可供選擇,就像尺寸單位一樣。

wrap_content——這個選項將會擴展元素的邊界到足夠的大小以致可以容納它包含的內容(圖片,文本等等),本質上,這個選項把元素設置成它最大子元素的大小,不會去調整元素的大小。

match_parent(fill_parent 在API 8中已過時)——這個選項會使元素適應父元素的大小,使用父元素最大的空間,減少間距。本質上,這使子元素爲父元素允許的最大尺寸的大小,並且必要的時候會調整元素的大小。

dimension unit——這個選項設置元素的邊界爲精確地單位大小,這些單位上文已經討論過。本質上,它會設置元素的邊界爲確定的單位大小,必要的時候會調整元素的大小。

Demo

爲了解釋這一切是如何一起工作的,創建並測試一個示例應用程序是必要的。例如,採用一個在密度爲xhdpi或320dpi,200X200 px的圖片的設計。簡單起見,將圖片資源命名爲“android_logo”。利用密度在320dpi,200X200 px圖像分辨率作爲所需的物理尺寸,可替換的圖像尺寸可以被計算出來。

                                  

                       密度爲xhdpi (320dpi),200x200px 的圖片

                

在計算完所需特定密度的圖像尺寸後,他們能夠在最大密度版本被縮小到相應的尺寸,如前面所解釋的那樣。接下來,每一個密度版本的圖片,能夠被放入到用相應資源標識符標記的“drawable”文件夾下。Android系統會根據設備上的配置,在運行時選擇最佳的資源。

                                             

                                               有標識符的資源目錄

現在,爲了呈現保持密度獨立的可能方式,利用每一種密度獨立的尺寸單位,將該圖片設置成相同的物理尺寸。因爲"px"不是密度獨立的,而"sp"是爲text設計的,因此忽略它們。

                 

 

 

設備例子:xhdpi Bucket

通過使用一個佈局,裏面包含相同的圖片,這些圖片是利用各種尺寸單位設置相同的物理大小,它可以比較每個尺寸單位是如何工作的。當運行在320 dpi的模擬器上,圖片會以完全相同的大小顯示,每一個尺寸單位都是這樣。這是意料之中的,因爲模擬器的dpi完全匹配xhdpi(320 dpi)密度等級。但是,當運行在同樣xhdpi 密度等級的Galaxy Nexus上時,圖片的大小尺寸會有一些變化。

 320dpi 模擬器截圖

           Galaxy Nexus 截圖

 

經過檢查發現,很顯然用"wrap_content"和"dp"設置的圖片在大小上是匹配的,與此同時,用"in","mm"和"pt"也是匹配的。但 是,這兩組沒有彼此匹配。到底發生了什麼事情呢?如之前討論,"wrap_content"和"dp"利用密度桶比率去適當地轉換它們的尺寸。因此,圖片 大小被計算到200x200 px。但是,Galaxy Nexus的實際屏幕密度並不是320 dpi,它是 315.3 xdpi和 318.7 ydpi。 因爲實際的密度低於320 dpi的xhdpi密度,因此在實際設備上的像素點會比想象的0.625 in的物理大小更大。

當分析用"in","mm"和"pt"設置圖片大小的時候,注意到每一個圖片被轉換爲 197.1x199.2 px。如之前討論,"in","mm"和"pt"都是利用實際設備的密度去轉換它們的尺寸到像素。因爲Galaxy Nexus的實際密度低於320 dpi的xhdpi密度,更少的像素需要被轉換爲0.625x0.625 in,這樣圖片就被縮小了。

當對所顯示的圖片進行對比時,很明顯,用"wrap_content"和"dp"設置的圖片物理尺寸精確度較低,但是它們的圖片質量比"in","mm"和"pt"更好。

沒有縮放"wrap_content"和"dp"(左)。有縮放"in","mm"和"pt"(右)

 

 

設備例子: hdpi Bucket

下一步,當運行在240dpi的模擬器上時,圖片以完全相同的大小顯示每一個尺寸單元。重複一下,之所以期望這樣是由於模擬器的dpi在240dpi的條 件下恰好匹配hdpi密度的桶(bucket)。但像以前一樣,當運行於hdpi設備時,出現一個不可思議的事情,圖像的尺寸有一些變化。

 

 

240dpi模擬器屏幕截圖

                             

 

 

 

HTC Droid Incredible截圖

像往常一樣,HTC Droid Incredible顯示150x150 px的圖片,該圖片用"wrap_content" 和"dp"設置。因爲Droid Incredible的實際屏幕密度爲254x254dpi,大於240dpi的hdpi密度,這意味着在屏幕上的像素小於240 dpi密度對應像素的大小。這就會導致150x150 px的圖片顯示要小於0.625 in的基礎大小。用"in","mm"和"pt"設置的圖片顯示爲158.8x158.8px,因爲需要更多的像素點轉換爲0.625x0.625 in,這樣該圖片就會被放大。

就像在Galaxy Nexus上,用"wrap_content"和"dp"設置的圖片物理尺寸精確度較低,但是它們的圖片質量比"in","mm"和"pt"更好。

沒有縮放"wrap_content"和"dp"(左)。有縮放"in","mm"和"pt"(右)

你能在GitHub找到該demo所有的源碼,或從後面的附件中獲得。

 

尺寸單位最佳實踐

px- 沒有保持密度獨立。應該永遠不需要。

in/mm/pt- 保持密度獨立,但是計算到確切數額的像素,會降低體驗,還會導致圖片顏色過渡不自然和走樣。如果需要尺寸大小的精確度,並且任何偏差都是不可接受的,那選擇in/mm/pt就是必要的。需要確切距離的時候,設置元素間的距離,in/mm/pt也是很有用的。

dp- 保持密度獨立並且保持最佳圖片質量,但是要在物理大小上,以小的偏差作爲代價。因爲它利用密度桶比率來進行計算大小,它適當地提供準確的尺寸與圖片資源。這是被推薦使用的尺寸單位,用來設置元素間的界限或者之間的距離。

sp- 保持密度獨立和字體的質量,但是要在物理大小上,以小的偏差作爲代價。這是被推薦使用的尺寸單位,僅僅用來設置字體大小,因爲它需要考慮密度和用戶的文本大小偏好。

 

 

總結

總的來說,保持密度獨立性的要點:

  • 確定每一個圖像資源確定呈現該資源所需的物理尺寸
  • 設計尺寸比最大密度桶更大的矢量圖像資源或原始圖像資源
  • 爲每一個密度桶創建特定的density 版本,然後將他們放入用合適標識符標識的“drawable”資源目錄下
  • 當設置圖像邊界的時候,用“wrap_content”來獲得最佳顯示效果,用“match_parent”來充滿整個顯示區域,或者用“dp”來設定一個固定的尺寸
  • 當在佈局裏面設定距離的時候,用“dp”獲得最佳顯示效果。如果需要使用精確的尺寸,僅用“in”,"mm"或"pt"。在這裏永遠別使用"px"

隨着對Android如何處理在不同密度的屏幕上顯示的理解,這將使得在任何密度的顯示屏上設計和開發最佳的應用程序變得更加容易。

 轉自http://www.cnblogs.com/xiaochao1234/p/4055931.html

英文原http://www.cnblogs.com/xiaochao1234/p/4055931.html文:Understanding Density Independence in Android 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章