[Xamarin.Android]不同解析度下的Layout設計以及圖片使用概論
設計Android App的時候,其尺寸眾多也是一個挑戰之一。要針對不同尺寸設計Android App時,就要先來了一下dpi(dots per inch,每一英吋的點數量)與ppi(pixel per square inch,每平方英吋的像素量)計算方式。這一篇研究就來討論一下在設計Android APP,如何因應不同的尺寸來作呈現。
n 首先dpi的定義是指每一英吋下,有多少像素(pixel)。
舉例來說,如果我的螢幕解析度設定成800X600pixel(72dpi),72dpi的意思就是每一個英吋裡面有72個像素(pixel)。所以先把螢幕解析度換算成英吋,(800/72)X(600/72)pixel = 11.1X8.3(英吋)。
n 螢幕的尺寸是如何計算公式
目前螢幕的尺寸是根據對角線的長度來定義。所以套用到數學畢氏定理的對角線計算公式就是
[長平方+寬平方=斜邊平方]。
n ppi計算公式(pixel per square inch,每平方英吋的像素量)
ppi = √長度像素平方+寬度像素平方÷螢幕尺寸
接下來參考一下Android官方網站提供的解析度尺寸對照圖表, 這是Android Device不同解析度對應到所存取的資源列表。
以解析度240x320的手機來說,若在APP開發中有針對低解析度的Device製作低解析度的圖片,則系統就會使用Low density的圖片。
*假設有一隻螢幕規格為3吋而解析度為(240X320)的手機,那我們就可以推算出它的ppi值,
√240⌃2+320⌃2/3=133,所以我們可以得到這個手機的ppi值是133。
n Android會自動根據你的手機尺寸來決定要用的圖檔是哪一個。
在設計支援多尺寸的App時,可以設計讓Android手機依照解析度的不同來存取不同的資源。
在Android專案中,圖片資源是被放在Drawable資料夾下。而我們可以依據不同的解析度需求來制作相對應的圖片資源,讓Android裝置去讀取適合他的圖片資源。在Android 專案中Resource下的資料夾結構有下列幾個資料夾,分別是[drawable-ldpi],[drawable-mdpi],[drawable-hdpi] ,[drawable-xhdpi]
。這幾個資料夾是用來放置不同解析度所相對應的圖片資源檔案。
再來看到這些圖片的比較基準。如果我們把放在mdpi資料夾下的圖片當做基準,假設這個圖片的比例是1的話。則存放在ldpi裡面裡的圖片檔案相對比例就是0.75x。而hdpi的相對應檔案就是1.5x,以此類推。
res/drawable-mdpi/my_icon.png // bitmap for medium density
res/drawable-hdpi/my_icon.png // bitmap for high density
res/drawable-xhdpi/my_icon.png // bitmap for extra high density
以Android官方網站提供的這個圖表來看,可以提供下列的比例參照方式去換算在制作圖檔時應該注意的尺寸比例。
36x36 for low-density
48x48 for medium-density
72x72 for high-density
96x96 for extra high-density
n 了解Android如何判斷目前Device該用哪一個資料夾裡面資源的方式
得知目前Device上的Density。Density數值是Android Device用來判斷它該用哪一個資料夾下的資源。
可以用底下方法列出目前Device的Density值。
var dp = Resources.DisplayMetrics.Density;
Console.WriteLine ("density = "+ dp);
原生的java會是這樣寫
float scale = getApplicationContext().getResources().getDisplayMetrics().density;
下方式列出來的Density值對應到所參照的資源取用依據。
0.75 means low density
1.0 means standard (medium) density
1.5 means high (large) density
2.0 means extra high density
n 除了圖片檔外,layout下的檔案也是可以依照解析度的不同來做區分
在Android架構中負責顯示layout的View畫面可以依據不同的解析度來做不同的呈現。
參考下方,Android有定義不同解析度對應到的layout尺寸,以及這個尺寸該被放在哪個相對應的資料夾下。
res/layout/my_layout.xml // layout for normal screen size ("default")
res/layout-small/my_layout.xml // layout for small screen size
res/layout-large/my_layout.xml // layout for large screen size
res/layout-xlarge/my_layout.xml // layout for extra large screen size
res/layout-xlarge-land/my_layout.xml // layout for extra large in landscape orientation
n 在AndroidManifest檔案新增支援不同解析度Device的XML語法。
<supports-screens android:resizeable=["true"| "false"]
android:smallScreens=["true" | "false"]
android:normalScreens=["true" | "false"]
android:largeScreens=["true" | "false"]
android:xlargeScreens=["true" | "false"]
android:anyDensity=["true" | "false"]
android:requiresSmallestWidthDp="integer"
android:compatibleWidthLimitDp="integer"
android:largestWidthLimitDp="integer"/>
n 在Xamarin studio中針對不同的解析度來建立相對應的View畫面。
Xamarin Studio的Android專案,在Layout設計工具中,在設計畫面的左上角,可以針對不同的解析度尺寸新增Layout中的View畫面。然後可以經由點選預設的一些尺寸對應來mapping到不同解析度的畫面設計。
在編輯畫面左邊按下[Mulit-edit],這三個Layout畫面會被連結起來,假如你拖拉一個Button進到其中一個畫面裡面,三個Layout都會自動新增起一個button控制項。這樣實在滿方便的。
當你編譯這個專案的時候,可以看到Xamarin自動幫你建立出不同layout畫面下的Main.axml檔案。
n 依照不同的解析度來放置圖片資源檔案
在Android的系統規範下,不同解析度的Device會自動存取適合自己解析度的圖片資源,
所以在設計圖片檔案的時候,就需要針對不同的解析度來設計圖片。而這些圖片資源必須以相同的檔案名稱存在於不同的相對應的資料夾,這樣在Android執行你的App的時候,會自動在相對應的路徑下去存取適合他的圖片。
n 在不同的解析度下,這邊我新增了三個主要的控制項,兩個文字標籤以及一個Imageview。
1. 第一個文字標籤上面會在不同的View上顯示[手機],[平板],[大平板]用來分辨我們現在到底載入了那一個Layout進來。
2. 第二個文字標籤是要顯示出目前Device的Density,來看看Android目前判斷出來的Device Density值。
3. 而ImageView是用來載入圖片,這裡Android系統會依據不同的Device解析度來載入相對應的圖片。
n 新增程式到對應layout的Activtiy
雖然這邊有三個不同的layout來對應不同解析度的Device,但是實際上,這三個Layout的名稱都叫做Main.axml。並且裡面的控制相名稱也都相同,這樣你並不需要用程式來為不同的Layout做判斷,這部分的設計還真是很不錯。所以可以看到底下的程式,在讀取圖片檔案到imageview的時候,這邊不需要在程式上做任何判斷。Android會依照Device的解析度來選擇最適合它的圖片資源。
n 在Genymotion模擬器中建立了建立三個不同解析度的Android Device 與我的實機一起來測試。
這四個不同解析度與尺寸的設備分別如下
解析度(480x800,240dpi )的Nexus One。
解析度(1024x600,160dpi)的WSVGA 7.0 Tablet。
解析度(1024x800,160dpi)的WXGA 10.1 Tablet。
解析度(1080x1776,480dpi)的Htc new one實機。
n 編譯程式
在WXGA 10.1 Tablet的模擬器上,由於它的解析度是1280x800,所以系統會自動抓到適合他的layout。
在圖片資源的部分,這個模擬器的dpi是160,所以這邊會抓到存放於mdpi裡面的圖片檔案。
在Nexus One的模擬器上,雖然它的解析度是480x800,但是它的dpi值為240,
在圖片資源的部分,它是自動抓取Ldpi資料夾裡面的圖片。
在我的手機上實測這支APP,我手機的解析度是1080x1776,而dpi值是480,在這個裝置上,他會取得xhdpi資料夾裡面的圖片支援。
n 最後在這邊研究,這邊下一個結論。
Android在判斷該存取哪一個layout中的View以及那一個資料夾中的圖片資源,並不是單單由螢幕尺寸來判斷。Android實際在判斷時會依據你的螢幕解析度還有dpi值來做判斷。
而解析度影響的是會從那一個Layout取出相對應的View顯示在裝置的畫面上。
而dpi值決定著Android會去哪一個資料夾裡面取用資源。
參考資料:
supports-screenssupports-screens
http://developer.android.com/guide/topics/manifest/supports-screens-element.html
Devices and Displays
http://developer.android.com/design/style/devices-displays.html
Supporting Multiple Screens
http://developer.android.com/guide/practices/screens_support.html
Devices and Displays
http://developer.android.com/design/style/devices-displays.html
Part 4 - Creating Resources for Varying Screens
List of displays by pixel density
http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density