多屏幕多分辨率的支持和一些概念
快速預覽
- Android 在不同的屏幕大小和密度上執行
- 屏幕的顯示會影響用戶界面的效果
- 系統處理大多數的自適應屏幕
- 你應該針對屏幕創建資源以更好的控制你的UI
Android 是一個系統,運行在這個系統上的很多設備它們的屏幕大小和密度都不一樣。但我們需要解決這個問題。本節爲詳細的爲你解釋一些基礎概念和教你怎麼處理關於多屏幕多分辨率的支持。 雖然系統會根據不同的屏幕來執行縮放和調整你的App,但你還是應該自己在加點外力來最大化用戶體驗的效果。
多屏幕支持概述
以下是一些術語和概念,大家要稍微留心看看:
屏幕大小
根據屏幕對角線實際測量的物理大小(android已經根據屏幕大小分爲四類small, normal, large, extra large)
屏幕密度
屏幕物理區域一個單位(一般用英寸)的像素數量,一般簡稱dpi(每英寸上的點數,記住DPI這個概念很重要)
這裏android也分爲四類 low, medium, high, extra high.
方向
從用戶的角度看設備只有2個方向,那就是橫屏和豎屏。關於橫豎屏最好也要出一套相對應的UI,因爲長寬比不一樣,放心難度不是很大。
分辨率
一個物理屏幕上像素點的總數。一般我們的App不會直接使用分辨率,而是使用密度和屏幕大小
獨立像素單位(Density-independent pixel (dp))
一個虛擬的單位,用來定於UI佈局的。用來表述佈局的尺寸或者位置。
dip(注 意dip是獨立像素單位,dpi是屏幕密度)等價於一個160dpi(mdpi)的屏幕,運行時系統會根據你實際屏幕的密度來自動處理縮放。像素和dip 的轉換公式爲dp =px*(dpi/160) 。例如在240密度(dpi)的屏幕上一個dp等於1.5個像素(dp=px*1.5)。以後我們應該儘量使用dip單位佈局,不要使用像素單位。這樣會使你的app屏幕兼容性更好
多屏幕可以看成是許多Boss,要戰勝這些boss有5點我們需要攻破它,分別是屏幕大小,屏幕密度,方向,分辨率,獨立像素單位。
屏幕大小-Boss的外在體型:熟悉每個boss的體型,會讓我們採取不同的戰術,大的笨重,小的輕巧
屏幕密度-Boss的密度:別看有個boss體型很小,他密度高,一個俄羅斯梅花坐直接壓死你,我們需要知道每個boss的密度。
方向-Boss的體型比:有的boss矮胖,看上去就像一個遊戲手柄,但有些高瘦,看上去就像一根棍子。但記住我們是站着看的,但如果躺着看呢,所以角度不同看出來的結果就可能不一樣
分辨率-boss的可識別度:隔boss近的話分辨率低,只能看到boss的某個部位而且很大,我不知道這是哪個boss;遠的話分辨率高,能看到boss的所有部位,哦!原來這個boss就是伊利丹怒風
獨立像素單位-boss的攻擊力:每個boss的攻擊技能都不太一樣,所以我們需要吧所有boss的技能轉換爲攻擊力來方便我們計算對付boss的策略
多屏幕支持的範圍
android1.6開始就支持多屏幕和密度了,這都是爲了更好的用戶體驗,爲了簡化我們多屏幕的開發。android提供一組範圍讓我們使用:
- 關於屏幕大小: small, normal, large, xlarge(看來目前boss的體型就這四種)
注意: 關於android3.2會有些不同,以後我們在講平板和手機支持時會說明
- 屏幕密度: ldpi (low), mdpi (medium), hdpi (high), xhdpi (extra high) (so 密度也是四種)
這些廣義的大小和密度都是基於normal大小和mdpi來配置的或者說相對論。一般來說我們手機800*480或者854*480 密度都是240(hdpi),屏幕大小爲large。
每一個大小和密度都有一個跨越幅度。但這些幅度中具體的微調我們是不用關心的,android會幫我們處理,下面我們來看圖
我們設計UI都會要考慮一個最小化的空間,android中都是使用dp(dip)單位的。
- xlarge 屏幕至少960dp x 720dp
- large 屏幕至少 640dp x 480dp
- normal 屏幕至少 470dp x 320dp
- small 屏幕至少 426dp x 320dp
屏幕大小和密度是可以獨立的,不是說一個5寸屏的密度就一定是hdpi。有一個很重要的例子就是例如一個WVGA (800×480)屏幕可能在不同的設備上會有mdpi和hdpid兩種密度,正常的屏幕密度應該是hdpi。但不用擔心我們是有辦法解決這種問題的。
就是說boss體型大不一定密度高,萬一它裏面真空呢。但也不要小看體型小的boss,有可能它裏面裝的都是金屬,你會很糾結怎麼打敗它。還有一些特殊的boss他體型一樣,但密度可以變化,真牛B的boss啊!先來個真空上陣,再直接用鐵砸死你。
獨立密度
維持獨立密度是很重要的,因爲沒有它,一個UI元素(比如一個按鈕)會出現在一個物理屏幕很大,但密度很少的顯示效果(看起來就是像是被強行放大的,失真很嚴重)。這樣相對位置的改變會出問題
android 系統幫助你的App實現獨立密度的方法有兩種:
- 系統縮放dp單位來適用當前屏幕密度The system scales dp units as appropriate for the current screen density
- 系統基於當前屏幕密度縮放drawable資源到適用的大小
圖 1是用像素單位來定義的大小。 你發現他們的佈局完全變了,有的大有的小。這是因爲他們的實際屏幕大小可能是一樣的,高密度屏幕每英寸的像素更多(所以你會發現像素一樣,但高密度的設備顯示出來的效果卻很小)。圖2使用的是dp單位,基於mdpi密度的設備它不會變化,ldpi它會自動縮小,hdpi它會自動放大。所以效果非常好。圖片 顯示出來的樣子和大小完全一樣。
使用密度系統會縮放圖片使之看上去完全一樣,但細心的你會發現有些圖片變模糊了。所以我們應該提供可選擇的圖片資源讓系統來選擇以適應不同的密度。所以以後工程項目中hdpi,mdpi,ldpi三個文件夾就是用在這裏的。這樣就不會有模糊的感覺了,perfect!!
我們一定要換算boss的攻擊力,好躲避技能,它的技能實在太多了,搞不好一口水就能淹死你(強力的攻擊啊)。
怎樣支持多屏幕(怎麼搞定這麼多boss)
以上我們學習了這麼多的理論基礎。我們應該優雅的處理它們了。
- 1.明確的在manifest文件中指出你的App支持的屏幕大小(哈哈,抓到你的小辮子了吧)
我們可以有選擇性的過濾掉一些老掉牙的設備,以減輕我們的工作量。但這並不是一個好的方法僅供參考。在manifest 中使用節點<supports-screens>
- 2.根據不同的屏幕大小提供不同的佈局(我們根據不同的boss體型來換不同的裝備應對,暗影系boss需要多穿點暗抗裝啊)
默認的android會調整你App的佈局來使用當前設備的屏幕。大多數情況下可以滿足,但某些特殊情況,你的UI可能需要一個更精確的調整。例如,一個larger 屏幕,你可能想要利用額外的屏幕控件調整位置和一些元素的大小,或者一個小屏幕中,你可能需要調整到剛好合適。比如你需要適應一個extra large 屏幕。你可以在文件夾layout-xlarge下放置佈局(大家記住一般layut下放的都是xml佈局文件)
Android 3.2開始,有一種新的放置方式。例如你的平板需求至少600dp的屏幕寬度,你可以使用layout-sw600dp
這種文件夾放置。以後我們在平板一節會詳細描述
- 3.根據不同的屏幕密度提供不同的位圖(根據不同的boss密度來學技能,你敢壓我?我有閃避 謝謝!)
默認android會縮放你的位圖(.png.jpg.gif),還有一種android專用的Nine-Patch(.9.png)。例如,你的App提供的位圖僅僅爲標準密度(mdpi),那麼在hdpi的屏幕上這些位置會被等比放大。所以我們應該有選擇性的對於不同的屏幕密度包含不同的分辨率。
所以android針對圖片資源配置後綴,前面我們知道的4種密度(ldpi.mdpi,hdpi,xhpi),如果是ldpi 我們應該使用drawable-
ldpi這種文件夾。以上關於屏幕大小和密度的後綴都符合屏幕支持的那些範圍。
注意: 如果你沒有熟悉的配置後綴, 不知道如何使用它們,沒關係。我們以後會在App資源中講解!
在運行時, 對於給定資源系統使用以下這些步驟保證你最佳的顯示:
- 系統會使用合適的替代資源
基於當前屏幕的大小和密度,系統會針對屏幕的密度和大小使用資源。例如,如果設備有一個 hdpi的屏幕那麼當App請求一個drawable 資源時,系統會在最匹配的的設備配置下的drawable 資源目錄尋找。可以取決於其他可替代的資源,使用
drawable-hdpi
的資源目錄最匹配的,所以系統會使用drawable-hdpi
目錄下的資源。 - 如果沒有可用的匹配資源,系統會使用默認資源等比放大或縮小以匹配當前屏幕的大小和密度。
這裏的默認資源是沒有後綴的。例如,“
drawable
”就是默認的drawable 資源。系統會認爲默認的資源都是基於normal 屏幕大小和medium 密度設計的。系統會等比縮放默認的密度資源來匹配hdpi密度或者ldpi密度。當系統沒有找到針對密度資源的目錄時,它就一直會使用默認的資源。例如,如果系統想找一個ldpi(低密度)的資源,但找不到。那麼系統會等比縮小hdpi的資源,爲什麼不尋找mdpi呢?因爲系統對於hdpi更容易縮放,它的係數爲0.5,相比mdpi的0.75來說。0.5的的性價比更高(方便計算,正確率也高一點)。關於這一點最好的證明就是android版本的QQ瀏覽器。你解壓後發現它關於drawable就只有drawable和drawable-hdpi兩個文件夾,看來騰訊裏android的開發者應該很熟悉android系統規律了,因爲默認的drawable 就是mdpi,只需要定義一套hdpi的drawable
資源就行了。
使用配置後綴
Android支持幾種配置後綴,它允許你控制系統有選擇性的篩選基於當前屏幕設備的資源文件。一個配置後綴就是一個String你可以在資源目錄文件夾下追加指定的後綴即可 。
使用一個配置後綴的方法步驟:
- 在你的工程res目錄下創建一個新的目錄,格式爲
<資源種類名>-<後綴>
:<
是標準的資源名字(例如 drawable或者layout)資源種類名
><
是指定屏幕配置使用哪一種資源(例如hdpi或者xlarge)後綴
>
我們可以使用的後綴不僅僅只有一個哦,在一個文件夾下我們可以同時使用多種後綴來限定資源,使用"-"即可。
- 在新的目錄中保存合適資源,資源文件的命名必須和默認資源文件一樣。
例如 xlarge是一個後綴用於
extra large 屏幕。當你追加後綴時(例如layout-xlarge
) ,它說明系統會在extra large屏幕上使用這些資源
裝備,技能齊全啊。求秒殺boss!!!
屏幕特徵 | 後綴 | 描述 |
---|---|---|
大小 |
small |
資源用於small大小的屏幕. |
normal |
資源用於normal 大小的屏幕。(這是默認的基準大小) | |
large |
資源用於large 大小的屏幕 | |
xlarge |
資源用於extra large 大小的屏幕 | |
密度 |
ldpi |
資源用於 low-density (ldpi) 密度的屏幕 (~120dpi). |
mdpi |
資源用於medium-density (mdpi) 密度的屏幕 (~160dpi). (這是默認的基準密度.) | |
hdpi |
資源用於high-density (hdpi) 密度的屏幕 (~240dpi). | |
xhdpi |
資源用於extra high-density (xhdpi) 密度的屏幕 (~320dpi). | |
nodpi |
資源用於所有密度. 系統不會根據當前屏幕密度去縮放資源 | |
tvdpi |
資源用於mdpi 和hdpi兩者之間的某的密度;大約是213dpi。 這個很少用到。它主要用於電視,大多數App不需要用到它。如果你需要tvdpi資源,它的大小大概是1.33*mdpi(160)例如,一個在mdpi下100px*100px的圖片,那麼在 tvdpi中它會變成133px*133px。 | |
方向 |
|
資源用於橫屏 |
|
資源用於豎屏 | |
長寬比 |
long |
資源用於長寬比相差很遠的配置(相對於4寸(normal)屏幕左右基準屏幕) |
notlong |
資源用於長寬比差不多的配置(相對論,同上) |
注意: 如果對於android3.2或者更高的版本,有一些新的後綴,等下我們會講解
下面我們就來舉一些詳細的例子
res/layout/my_layout.xml // 用於normal 屏幕大小的佈局 ("默認") res/layout-small/my_layout.xml // 用於small 屏幕大小的佈局
res/layout-large/my_layout.xml // 用於large屏幕大小的佈局
res/layout-xlarge/my_layout.xml // 用於extra large屏幕大小的佈局
res/layout-xlarge-land/my_layout.xml // 於extra large屏幕大小並且是橫屏的佈局
res/drawable-mdpi/my_icon.png // 用於中等密度的位圖
res/drawable-hdpi/my_icon.png // 用於高密度的位圖
res/drawable-xhdpi/my_icon.png // 用於超高密度的位圖
當android系統在運行時選擇資源時,它會以一定的邏輯判斷來匹配最適合的資源。前提是你沒有加後綴。當基於使用大小的後綴時,如果當前沒有資源更好的匹配你的後綴,那麼系統會使用
比當前屏幕更小的資源來計算(例如,如果你沒有添加large後綴,那麼一個large大小的屏幕將會使用在normal(默認的)大小的屏幕資源),如果可用的資源後綴比當前屏幕更大(其實還是沒匹配
上),那麼系統將不使用它們(例如你吧所有layout資源放入xlarge後綴中,但設備是一個normal屏幕,系統就不會使用這些資源)。
是不是有點頭暈了,簡要的概述下就是如果沒有匹配的系統會使用默認的資源,如果連默認下都沒有放資源並且沒有匹配到你的後綴,那麼系統就沒有資源可用啦。
注意:某些情況下你可能需要用到nodpi後綴,因爲你可能不想要它被縮放,或者你想要在運行時通過代碼手動縮放它。
設計可供選擇的layouts(裝備)和drawables(技能)
你應該根據於你App的需求來創建可供選擇的資源類型。通常,你應該使用大小和方向後綴來提供可選擇的Layout資源,使用密度後綴來提供可選擇的位圖drawable資源
可供選擇的佈局(layouts)
你應該知道你的App是否有這個需求,是否需要根據不同的屏幕來提供可選擇的佈局。例如:
- 當在一個small屏幕上測試時,你發現你的佈局沒有完全符合你的要求或者是沒有匹配好屏幕。例如一排按鈕沒有很好的在small屏幕上顯示。這種情況你應該爲small屏幕提供一個可供選擇的佈局用來調整按鈕的大小或者位置。
- 當在一個extra large屏幕測試時, 如果沒有有效利用大屏幕或者明顯的被拉伸了,這種情況你也應該提供一種根據extra large屏幕的佈局,並且最好再優化它以適應將來的平板設備
雖然你的App沒有提供大屏幕的佈局運行起來也沒問題,但UI被明顯拉伸的感覺會讓用戶覺得這個APP不太精緻,用戶體驗會大打折扣
- 當在橫屏和豎屏對比測試時, 你應該注意到UI元素在豎屏下是在底部,橫屏下卻是右邊。如果你一直需要都在底部的話,你也應該配置後綴
總的來說,你應該確保你的App佈局如下:
- 適用於小屏幕
- 優化App使之在大屏幕上利用額外的空間
- 優化橫豎屏
如果你的UI使用位圖,那麼你應該使用nine-patch (超牛B特殊技能,目前遊戲版本沒更新,以後更新了馬上給學了)位圖文件。nine-patch 這是android提供的一種格式並且它還提供一種根據讓你吧美工出的圖片稍微修飾。這種格式能允許你設置可以縮放的2D範圍。當系統需要縮放時,系統會在你指定區域縮放 Nine-Patch位圖。這樣在不同的屏幕大小下你就不需要提供不同的位圖資源了(可以節省APK的大小)。因爲Nine-Patch會自動調整它的。但在不同的屏幕密度下你應該還是提供可供選擇的Nine-Patch 文件。這樣你的APP纔會更健壯。關於nine-patch的使用我們以後會在第二大篇的圖形章詳細講述。
可供選擇的drawables
幾乎每一個App都會根據不同的密度提供可選擇的drawable資源,因爲這對於用戶體驗和UI真的很重要。
注意: 根據密度你僅需要提供drawable下的位圖文件,如果你使用Xml來定義shape,colors或者其他drawable的資源,你就應該放到"drawable/
"默認目錄下
根據不同的密度提供可選擇的位圖drawable資源時,你應該在四種密度下使用3:4:6:8的縮放比。你可以參考工程下每個不同的drawable裏的icon尺寸。以下是數據:
- 36x36 ldpi
- 48x48 mdpi
- 72x72 hdpi
- 96x96 xhdpi
關於Android 3.2平板上的佈局
第一代平板運行於android3.0上,一般是使用xlarge配置後綴(res/layout-xlarge/
)來聲明平板佈局。爲了提供其他類型的平板和屏幕大小----尤其是7寸平板!android3.2引入了一種新的方法來爲更多離散的屏幕大小來指定資源。你的佈局需要一種新的基於控件容量的技術(例如指定600dp的寬度),而不是試圖使你的佈局去適應那些android概括性的分組(例如large或xlarge)
當android去概括大小分組時,對於7寸平板他們也很棘手,因爲5寸手機和7寸平板使用同樣的large組。這兩個設備在size上表面上看起來更貼近彼此,但其實UI在相當大程度上還是不同的,用戶體驗的效果也不太好。因此一個7寸和5寸的屏幕將不使用同樣的layout。根據這兩種屏幕你應該儘可能的提供不同的佈局,android現在允許我們指定基於寬度或高度layout資源,記住請使用dp單位。
例如, 在你根據平板風格設計佈局以後,你可能需要當屏幕小於600dp的寬度時候停止工作。這個界限會因爲你的平板佈局而變成最小的尺寸。這樣你能立刻指定當至少寬度在600dp時候,layout中的資源文件才被用到。
注意: 記住!dip是一個非常重要的單位,你的佈局大小也應該用dp單位。因爲它可以看做一種比例單位而非像素那樣的絕對單位。
使用新的大小後綴(非密度)
你能爲你的佈局指定不同的資源配置。在下方的表格2中這些新的後綴提供給你更多的控制,相對於傳統的(small, normal, large, and xlarge)這些已經超過它們了
注意: 你指定使用的這些後綴並非實際的屏幕大小。當然,這些大小是根據寬度(dp單位)和高度(dp單位)被用於activity的window中。window的特殊性在於它方法是有個動作條,用來顯示電池和通知信息的。所以你在設計UI的時候需要考慮 你的App是否需要顯示動作條。
屏幕 配置 | 後綴值 | 描述 |
---|---|---|
最小寬度 |
sw<N>dp 例如: sw600dp sw720dp |
用這個後綴可以確保不管當前屏幕是否橫豎屏。你的App有一個至少<N>dp的可用寬度 例如, 如果你的layout一直需求最小屏幕的一邊爲600dp,那麼你能使用這個後綴創建layout資源( 設備的最小寬度要考慮屏幕的裝飾和系統UI。例如,如果設備有一些持續不變的沿着你最小寬度的軸方向的UI元素(動作條等),那麼系統會宣佈最小寬度比實際屏幕寬度要小,因爲那些UI元素對於你的UI來說是不可用的 因爲寬度是經常影響佈局的一個重要因素,所以使用最小寬度來控制一般的屏幕大小(針對平板)還是有用的。 可用寬度也是決定是否使用單屏幕布局(手機)和多屏幕布局(平板)關鍵因素,因此你很可能關心每一個設備上的最小方面。 |
屏幕可用寬度 |
w<N>dp 例如: w720dp w1024dp |
用dp單位指定一個最小化的在可用寬度下可以使用的資源。系統會根據寬度改變(橫豎屏切換時)來匹配這個值,並反映到當前實際可用的寬度上 當你決定是否使用多屏幕布局時它很有用,因爲即使在平板設備上,你也經常不想要多屏幕布局會根據橫豎屏來變化。因此你可以用這個來指定最小化的寬度需求,它可以用來代替方向後綴(land,port)和大小後綴(small,normal,large,xlarge)使之整合到一起。 |
屏幕可用高度 |
h<N>dp 例如: h720dp h1024dp etc. |
用dp單位指定一個最小化的屏幕高度。和"屏幕可用寬度"類似 |
當使用這些後綴時你可能覺得比傳統的那四種後綴複雜些,實際上你用過後就發現它很簡單,它能一次簡化你的UI需求。當你設計UI時,主要的事情就是需要考慮我們App中的實際大小,並且對於手機和平板風格的切換。它取決於你某些特定切換點的設計,可能對於平板佈局你需要720dp的寬度,可能600dp就足夠了,或者480,或者這兩個之間。使用表格2的後綴,你可以在佈局改變時精確的控制大小。以後我們會根據實際開發來講述的
配置例子
以下是一些屏幕數據:
- 320dp: 一種手機屏幕(240x320 ldpi, 320x480 mdpi, 480x800 hdpi, 等).
- 480dp: 一種平板 (480x800 mdpi).
- 600dp: 7寸平板(600x1024 mdpi).
- 720dp: 10寸平板(720x1280 mdpi, 800x1280 mdpi, 等).
我們使用表格2中的後綴來爲我們的App定義不同的切換風格(包括手機和平板),例如, 如果我們的平板佈局600dp是最小可用寬度,我們能提供兩套佈局方式:
res/layout/main_activity.xml # 手機
res/layout-sw600dp/main_activity.xml # 平板
這種情況下,屏幕可用的最小寬度爲600dp,這是僞了支持平板佈局被應用。
或者你可能想要區分7寸和10寸平板,你可以這麼做:
res/layout/main_activity.xml # 手機(比600dp更小的可用寬度) res/layout-sw600dp/main_activity.xml # 7寸平板 (600dp的寬度或者更大) res/layout-sw720dp/main_activity.xml # 10寸平板(720dp的寬度或者更大)
注意上面的兩套例子的使用使用 sw(最小寬度)後綴,它指定屏幕的兩邊中的最小一邊,不管屏幕的水平方向。它忽視橫豎屏。
然而某些情況下我們需要精確佈局。例如如果你有一個 2個面板合併在一起的顯示效果。是否屏幕提供至少600dp的寬度,是否橫豎屏你都要使用它。就應該這:
res/layout/main_activity.xml # 手機(小於600dp的可用寬度) res/layout-w600dp/main_activity.xml #多面板 (任意一個面板都是600dp或者更高的寬度)
注意上面這裏用的是w<n>dp。實際設備可能需要兩套佈局,它依賴於屏幕的水平方向(一邊至少是600dp的寬度,另一邊小於600dp,你會發現不管橫豎屏都滿足這個條件。所以你需要準備兩套關於橫豎屏的佈局)
關於什麼是多屏手機或者叫多面板手機。我發個圖給大家看看就明白了(下面這個手機其實有3屏)
關於聲明屏幕支持的大小
在android3.2的manifest 中引入了<supports-screens> 節點,以後再講manifest 文件的時候我們會詳細描述
實踐中應該注意哪些
在多樣的屏幕中我們使用傳統的四種配置還是能很好的獲得支持的。上面我們提供了多種定義的方法。添加這些後綴能確保你的App能適應不同的屏幕設備。
下面是一些方法,告訴你如何確保你的應用程序可以正確地顯示在不同的屏幕上:
- 在XML佈局文件中請使用
wrap_content
,fill_parent
, 或者dp
單位 - 在你的程序代碼中最好不要使用像素(px)這種硬編碼
- 不要使用
AbsoluteLayout
(絕對佈局) - 提供不同的位圖drawable資源來適應不同的屏幕密度.
1. 使用在XML佈局文件中請使用wrap_content
, fill_parent
, 或者 dp
單位(裝備附魔要搞好)
當在XML中爲你的Views定義android:layout_width
和
android:layout_height
時, 使用"wrap_content"
, "fill_parent"
或者dp
單位來保證View在當前屏幕上獲得一個合適的大小。
例如,一個view的寬爲layout_width="100dp"
在mdpi的屏幕下它是100px,在hdpi的屏幕下它就是150px,但顯示出來的效果在物理屏幕上是一樣的大小
同樣, 對於定義文本的大小,我們應該用sp(scale-independent pixel)。 因爲sp和dp的概念是一樣的,它們不是絕對的像素值
2.在你的程序代碼中最好不要使用像素(px)這種硬編碼
由於執行原因並使代碼更簡單,android系統使用像素作爲標準單位用來描述尺寸或座標值。就是說在代碼中android還是使用的像素用來表述尺寸,但它是基於當前屏幕密度的,所以是變化的。如果代碼中 View.getWidth()返回的值是10,這麼這個10的單位爲像素,但這僅僅是在某一個密度的屏幕上而已,其他不同密度的屏幕上它的結果就會不一樣了。所以android是不建議我們在代碼中用像素來設置佈局的,因爲它會加重我們的工作量,並且處理的也不一定很好。想象一下這麼多屏幕設備你如果用代碼來適配的話,你就得考慮的非常嚴謹了。不過如果你只針對某一種屏幕的話就另當別論了,但這種情況很少見。
3.不要使用AbsoluteLayout
(絕對佈局)(這種裝備out了,趕緊摧毀)
請不要使用AbsoluteLayout(絕對佈局)這種佈局是早期android的版本,在android1.5版本的時候就已經廢棄了。雖然爲了兼容以前很老的設備這種佈局還存在,但
目前來說,我們已經完全沒有必要再使用它了。
4.提供不同的位圖drawable資源來適應不同的屏幕密度.(根據不同的boss我們應該選相應的技能哦)
雖然在當前屏幕配置上系統會自動縮放你的layout和drawable資源,但爲了優化某些特定密度的設備,可能我們並不想讓它縮放,我們想給這種密度指定一套資源也是可以而且這樣的效果也
很不錯,能更好的根據不同的屏幕來調整我們的UI。這個我們在本文中已經反覆提到了,目的就是爲了加深你的印象。
一個很好的例子就是關於你用eclipse生成android工程的時候,三種不同的drawable(res/drawable-ldpi/icon.png,res/drawable-mdpi/icon.png,res/drawable-hdpi/icon.png)中都
會自動生成不同尺寸的icon.png。
注意: 如果我們沒有定義某個後綴,但屏幕密度又是需要那個後綴的話,那麼系統會假定你的資源都是基於mdpi(默認)的。並會放縮你的資源
關於密度額外的注意事項
這一段主要描述android在不同屏幕密度上是怎麼縮放位圖drawable的,我們需要更進一步的掌握系統控制位圖資源的原理。
當在運行時操作圖形,我們能更好的理解它是怎樣支持多屏幕的,我們應該瞭解下系統是如何保證適應屏幕並適當的縮放位圖的:
- 載入時自動縮放 (比如位圖drawables)--根據boss密度自動選擇技能?這真太智能了
基於當前屏幕的密度,系統使用任意大小或者密度的資源來顯示它們的時候是沒有縮放過的。如果在當前密度下沒有可用的資源,那麼系統會載入默認資源並等比縮放它們來匹配當前屏幕的密度。除非有有針對密度的後綴出現,不然系統都是認爲默認資源(沒有後綴的drawable)是爲mdpi的密度來設計的。因此係統這個時候會調整位圖的大小來適應屏幕。
如果你需求資源縮放之前的大小,那系統實際上返回的是縮放後的大小。例如:如果你沒有指定hdpi後綴,一個在mdpi下50px*50px的位圖在一個hdpi下會縮放爲75px*75px。在hdpi屏幕下系統會返回這個75px這個大小。
如果你不希望系統根據不同的密度來縮放資源,那麼請記住使用“res/drawable-nodpi/”
- 運行時自動縮放(比如像素的大小和座標)--打boss的時候在自動選?這也挺牛B
一個App能關閉載入時自動縮放的這個功能,只要你在manifest中設置
android:anyDensity
="false",或者在程序中使用
會在繪製的時候自動等比縮放任何絕對座標和像素大小。這麼做確保用針對像素的屏幕元素能一直顯示。系統會處理縮放,然後轉化並報告縮放的像素大小,而不是物理像素大小。下面我們來舉個例子:BitmapFactory.Options.inScaled返回的值爲false。在這種情況下。系統
例如,假設一個設備有一個WVGA(800*480)下是hdpi的屏幕,並且它和在傳統的HVGA(480*320)屏幕一樣的物理大小,但執行App的時候關閉了載入時自動縮放這個功能。這樣的話,當系統查詢屏幕大小時,它會認爲誰TMD的這麼坑爹。然後他會報告一個320*533的大小,爲什麼會是320*533呢,我們開的模擬器是800*480的啊!!因爲系統在繪製的時候縮放了。系統報告的是縮放後的像素大小,而不是我們模擬器上的物理大小。然後App需要繪製操作時,本來想在(10,10)上的位置繪製,但會變成(15,15)。如果你的App直接操作縮放位圖,那這種差異可能導致意外的行爲。以前很多剛開始接觸android的朋友經常會遇到系統報告320*533的這種問題。原因就是由於我們關閉了載入時自動縮放這個功能。你關閉了它的話,它就會在運行時縮放並返回結果。所以我們要檢查manifest中是否設置
android:anyDensity
="false
"。如果有趕快去掉。也許還有朋友發現沒有設置怎麼也會出現這種問題,這是由於以前比較老的SDK版本系統默認設置關閉了載入時自動縮放這個功能導致的,不過目前這種情況很少發生了。
運行時創建縮放的位圖對象
我們的App如果需要在內存中創建一個位圖(bitmap)對象,那麼系統會認爲你是基於mdpi密度的屏幕來創建的。默認的,系統會根據屏幕密度在繪製的時候自動縮放這個位圖。當位圖沒有指
定密度屬性時候,系統會自動縮放。爲了控制位圖在運行時創建後是否被縮放,我們可以指定位圖的密度屬性,使用Bitmap.setDensity()。具體的值可以傳DisplayMetrics
.DENSITY_HIGH
或
其他。我們還可以從文件或者一個流中使用BitmapFactory
來創建位圖,使用BitmapFactory.Options來定義位圖的屬性,那麼系統會根據你的屬性來縮放它。我們還可以使用
BitmapFactory.Options
.inDensity來指定這個位圖是否需要匹配當前的屏幕密度。如果我們設置
=false;那麼系統在載入位圖時將不會自動縮放它,只會在BitmapFactory.Options
.inDensity
運行時縮放它。使用運行時縮放CPU佔用率高,內存佔用低。使用載入時縮放CPU佔用率低,內存佔用高。如何取捨就看你的需求了。
dp 和 像素的轉換(攻擊力有時候還需要轉成技能的)
有些情況下,dp和px只需要相互轉換的。例如一個App在用手指滑動屏幕的時候會感應用戶的手指移動了多少個像素。在一個normal和mdpi的屏幕下,用戶必須移動16px/160dpi,等價於十分之一英寸(大約2.5mm(毫米))。那麼在一個hdpi(240dpi)的屏幕上用戶必須移動16px/20dpi,等價十五分之一英寸(1.7mm)。距離是很短的,因此這對用來說會很敏感。爲了修復這個問題,需要用代碼吧dp轉換成px單位。例如:
// 手勢的響應的範圍(dp) privatestaticfinalfloat GESTURE_THRESHOLD_DP =16.0f; // 獲取屏幕的密度來縮放 finalfloat scale =getResources().getDisplayMetrics().density; //根據密度吧dp轉換成px mGestureThreshold =(int)(GESTURE_THRESHOLD_DP * scale +0.5f); // 可以使用這個響應的範圍了
這裏
的值爲(0.75[ldpi],1[mdpi],1.5[hdpi],2[xhdpi]) ,其實我們還可以使用DisplayMetrics.density
ViewConfiguration
類來處理,但前提是打開了載入時縮放這個功能(目前來說,默認都
是開的不用擔心)並且我們可以使用ViewConfiguration
. getScaledTouchSlop()
來直接獲得換算距離。具體使用如下:
privatestaticfinalint GESTURE_THRESHOLD_DP =ViewConfiguration.get(myContext).getScaledTouchSlop();
在多種屏幕下怎樣測試我們的App
在發佈我們的應用之前,我應該在不同的屏幕大小和密度上測試我們的App。android SDK中有很多模擬器,我們可以修改模擬器上的默認的大小,密度,分辨率來整合測試。例如使用android2.1版本的模擬器,我們可以同時新建多個2.1的版本,但每個的密度不同。這麼多模擬器可以爲我們省下很多錢來買不同的手機。如果你想修改某個模擬器的密度,你只需要選中它點擊右邊的edit就可以修改了。如下圖所示:
爲了測試App是否支持多種不同的屏幕,我們應該創建一系列的AVD(android virtual devices)。如果不用eclipse的話,我們可以在sdk目錄下執行SDK Manager.exe這樣就顯示出圖5的界面
關於android虛擬機的管理和使用我們以後會詳細描述。
Low density (120), ldpi | Medium density (160), mdpi | High density (240), hdpi | Extra high density (320), xhdpi | |
---|---|---|---|---|
Small screen | QVGA (240x320) | 480x640 | ||
Normal screen |
WQVGA400 (240x400) WQVGA432 (240x432) |
HVGA (320x480) |
WVGA800 (480x800) WVGA854 (480x854) 600x1024 |
640x960 |
Large screen |
WVGA800(480x800) WVGA854 (480x854) |
WVGA800(480x800) WVGA854 (480x854) 600x1024 |
||
Extra Large screen | 1024x600 |
WXGA (1280x800)? 1024x768 1280x768 |
1536x1152 1920x1152 1920x1200 |
2048x1536 2560x1536 2560x1600 |
? 表示用於android3.0的平臺 |
建議大家啓動模擬器的時候最好不要縮放,這樣看起來的結果是物理屏幕上區別就不會很大了。當你從AVD Manager啓動一個模擬器時,我們指定的dpi的時候,可以和自己顯示器匹配下。
如果我們需要使用命令啓動的話,可以這樣啓動:
emulator -avd <avd_name>-scale 96dpi
總結:
關於android的屏幕和分辨率,這是非常重要的一個知識點,希望大家認真學好它,在以後的開發過程中絕對是非常有幫助。
現在我們稍微回顧一下關鍵的內容:
一,Boss的5個關鍵點
1.體型(屏幕大小)
2.體型的密度(屏幕密度)
3.體型比(屏幕的方向)
4.可識別度(屏幕的分辨率)
5.攻擊力(dp單位)
二,我們也有相應的對策對付他們
drawable(我們遊戲角色的技能,目前4種(ldpi,mdpi,hdpi,xhdpi))
layout(我們遊戲角色的裝備,目前4種(small,normal,large,extra large))
三,怎麼樣適應各個boss,讓我們輕鬆搞定它們
manifest文件中指出你的App支持的屏幕大小
根據不同的屏幕大小提供不同的佈局
根據不同的屏幕密度提供不同的位圖
四,最後我們需要熟悉後綴和一些公式
目前那麼多後綴不需要完全記住(以後用的多自然就記住了),但需要有個印象(後綴可以爲drawable服務,也可以爲layout服務,你可以想象成後綴既是寶石--附魔嵌在裝備(layout)上的,又是銘文--提高技能(drawable)傷害或其他技能功能的)
還記得3:4:6:8嗎? 還記得 0.75x, x ,1.5x, 2x嗎?這些都很重要哦
下一節我們繼續還是講多屏幕的適配,但都比較具體的實例,大家應該很喜歡的,但前提是吧這一節的理論鞏固好!