天天看點

Android 螢幕适配方案(七)

原文位址為: Android 螢幕适配方案(七)

一、 手機适配的應用和使用場景

使android應用程式适用于不同的國家語言、型号、尺寸和SDK版本等手機環境中,其主要功能和界面風格保持不變。

手機适配主要包括三個方面:語言适配、螢幕适配、SDK平台的适配

最複雜最麻煩的是螢幕适配。

二、 語言适配

主要用于文本内容的國際化。如按鈕的标題、輸入提示資訊等

當把app裝中不同的語言環境中的手機中,app應該能夠适應不同的手機來顯示不同的語言。例如:安裝中中文的手機上應該顯示中文,安裝到英文的手機上應該顯示英文。如果做到這些呢?就需要進行多國語言的适配。

步驟:

1、 建立Android xml檔案。資源類型選擇values,文本資源的檔案名一般命名為strings。

2、 點選下一步。選擇Language和Region

3、 選擇Language。選擇zh(中文)

4、 選擇region。填寫cn(中國)

5、 點選finish會生産如下目錄。(最終目的。當然也可以直接手動建立這個目錄)。當中中文系統下,使用字元串資源的時候,會自動加載這個目錄下的字元串資源。

另外再建一個中文英文目錄:

values-en-rUS

系統中适配字元的時候會首先去相應的目錄下找,如果找不到就去預設的/res/values下找。

相應的語言:

中文(中國):values-zh-rCN

中文(台灣):values-zh-rTW

中文(香港):values-zh-rHK

英語(美國):values-en-rUS

英語(英國):values-en-rGB

英文(澳洲):values-en-rAU

英文(加拿大):values-en-rCA

英文(愛爾蘭):values-en-rIE

英文(印度):values-en-rIN

英文(紐西蘭):values-en-rNZ

英文(新加坡):values-en-rSG

英文(南非):values-en-rZA

阿拉伯文(埃及):values-ar-rEG

阿拉伯文(以色列):values-ar-rIL

保加利亞文: values-bg-rBG

加泰羅尼亞文:values-ca-rES

捷克文:values-cs-rCZ

丹麥文:values-da-rDK

德文(奧地利):values-de-rAT

德文(瑞士):values-de-rCH

德文(德國):values-de-rDE

德文(列支敦士登):values-de-rLI

希臘文:values-el-rGR

西班牙文(西班牙):values-es-rES

西班牙文(美國):values-es-rUS

芬蘭文(芬蘭):values-fi-rFI

法文(比利時):values-fr-rBE

法文(加拿大):values-fr-rCA

法文(瑞士):values-fr-rCH

法文(法國):values-fr-rFR

希伯來文:values-iw-rIL

印地文:values-hi-rIN

克羅裡亞文:values-hr-rHR

匈牙利文:values-hu-rHU

印度尼西亞文:values-in-rID

意大利文(瑞士):values-it-rCH

意大利文(意大利):values-it-rIT

日文:values-ja-rJP

韓文:values-ko-rKR

立陶宛文:valueslt-rLT

拉脫維亞文:values-lv-rLV

挪威博克馬爾文:values-nb-rNO

荷蘭文(比利時):values-nl-BE

荷蘭文(荷蘭):values-nl-rNL

波蘭文:values-pl-rPL

葡萄牙文(巴西):values-pt-rBR

葡萄牙文(葡萄牙):values-pt-rPT

羅馬尼亞文:values-ro-rRO

俄文:values-ru-rRU

斯洛伐克文:values-sk-rSK

斯洛文尼亞文:values-sl-rSI

塞爾維亞文:values-sr-rRS

瑞典文:values-sv-rSE

泰文:values-th-rTH

塔加洛語:values-tl-rPH

土耳其文:values--r-rTR

烏克蘭文:values-uk-rUA

越南文:values-vi-rVN

三、 螢幕适配

3.1 Android螢幕适配出現的原因

Android碎片化太嚴重!!!

據統計:

2012年,支援Android的裝置共有3997種。

2013年,支援Android的裝置共有11868種。

2014年,支援Android的裝置共有18796種。

下面這張圖檔所顯示的内容足以充分說明當今Android系統碎片化問題的嚴重性,因為該圖檔中的每一個矩形都代表着一種Android裝置。

而随着支援Android系統的裝置(手機、平闆、電視、手表)的增多,裝置碎片化、品牌碎片化、系統碎片化、傳感器碎片化和螢幕碎片化的程度也在不斷地加深。而我們今天要探讨的,則是對我們開發影響比較大的——螢幕的碎片化。

下面這張圖是Android螢幕尺寸的示意圖,在這張圖裡面,藍色矩形的大小代表不同尺寸,顔色深淺則代表所占百分比的大小。

而IOS裝置則好很多!!!

3.2 關于尺寸的幾個重要概念

1、 螢幕尺寸

螢幕尺寸螢幕尺寸指螢幕的對角線的長度,機關是英寸,1英寸=2.54厘米比如常見的螢幕尺寸有:2.4、2.8、3.5、3.7、4.2、4.7、5.0、5.5、6.0等

2、 螢幕分辨率

螢幕分辨率是指在橫縱向上的像素點數,機關是px,1px=1個像素點。一般以橫向像素數*縱向像素數 表示,如1960*1080。

3、 螢幕像素密度

螢幕像素密度是指每英寸上的像素點數,機關是dpi,即“dot per inch”的縮寫。螢幕像素密度與螢幕尺寸和螢幕分辨率有關,在單一變化條件下,螢幕尺寸越小、分辨率越高,像素密度越大,反之越小。一英寸裡面有160個像素,這個螢幕的像素密度就是160dpi。

4、 dp、dip、dpi、sp、px

a) px:像素。我們應該是比較熟悉的,前面的分辨率就是用的像素為機關,大多數情況下,比如UI設計、Android原生API都會以px作為統一的計量機關,像是擷取螢幕寬高等。

b) dip和dp是一個意思,都是Density Independent Pixels的縮寫,即密度無關像素,上面我們說過,dpi是螢幕像素密度,假如一英寸裡面有160個像素,這個螢幕的像素密度就是160dpi,那麼在這種情況下,dp和px如何換算呢?在Android中,規定以160dpi為基準,1dip=1px,如果密度是320dpi,則1dip=2px,以此類推。

假如同樣都是畫一條320px的線,在480*800分辨率(像素)手機上顯示為2/3螢幕寬度,在320*480的手機上則占滿了全屏,如果使用dp為機關,在這兩種分辨率下,160dp都顯示為螢幕一半的長度。這也是為什麼在Android開發中,寫布局的時候要盡量使用dp而不是px的原因。

c) 而sp,即scale-independent pixels,與dp類似,但是可以根據文字大小首選項進行放縮,是設定字型大小的禦用機關。

d) dp/sp轉px : px=dp*密度系數 (密度系數:螢幕的dpi/160)

5、 mdpi、hdpi、xdpi、xxdpi

其實之前還有個ldpi,但是随着移動裝置配置的不斷更新,這個像素密度的裝置已經很罕見了,所在現在适配時不需考慮。

mdpi、hdpi、xdpi、xxdpi用來修飾Android中的drawable檔案夾及values檔案夾,用來區分不同像素密度下的圖檔和dimen值。

Google對mdpi、hdpi、xdpi、xxdpi官方标準:

在進行開發的時候,我們需要把合适大小的圖檔放在合适的檔案夾裡面。下面以圖示設計為例進行介紹。

圖檔的選擇規則:

Android系統尋找圖檔的步驟是這樣的:

1, 去螢幕密度對應的目錄去找。如果找到就拿來用。

2, 如果沒找到,就去比這個密度高一級的目錄裡面去找,如果找到就拿來用。

3, 如果沒找到就繼續往上找。以此類推。

4, 如果到了xxhdpi目錄還沒有找到的話,就會去比自身螢幕密度低一級的目錄去找,如果低一級的目錄>=hdpi,找到了就拿來用。

5, 如果沒找到, 就去mdpi目錄去找, 如果找到了,就拿來用。

6, 如果沒找到,就去預設的drawble目錄裡去找, 如果找到了就拿來用。

7 ,如果沒找到,再去最低的ldpi目錄裡去找。如果找到了,就拿來用。

8, 如果沒找到, 那就是沒找到了, 圖檔無法顯示。(不過一般不會出現這種現象,因為如果每個目錄都沒有這個圖檔的話,你是編譯不過的)

這裡有兩點需要注意:

① 首先會去比自己密度高的目錄裡去找,這是因為因為系統相信,你在密度更高的目錄裡會放置分辨率更大的圖檔,這樣的話這個圖檔會被縮小,但同時顯示效果不會有損失,但是如果優先去低一級别的目錄去找的話, 找到的圖檔就會被放大,這樣的話這個圖檔就會被拉扯模糊了。

e.g. 同一張圖檔,你在mdpi和xxhdpi目錄各放了一份, 這個應用你現在運作在hdpi的手機上, 那應用會選擇哪張圖檔呢。答案是xxhdpi目錄裡的。即便hdpi離mdpi更近一點!

②,如果在mdpi裡找不到是不會直接去ldpi裡找的, 而是先去預設的drawble目錄裡找,這是drawble目錄和drawble-mdpi是一個級别的。

3.3 解決方案

3.1.1 支援各種螢幕尺寸

1、 使用wrap_content、match_parent、weight

要確定布局的靈活性并适應各種尺寸的螢幕,應使用 “wrap_content” 和 “match_parent” 控制某些視圖元件的寬度和高度。

使用 “wrap_content”,系統就會将視圖的寬度或高度設定成所需的最小尺寸以适應視圖中的内容,而 “match_parent”(在低于 API 級别 8 的級别中稱為 “fill_parent”)則會展開元件以比對其父視圖的尺寸。

如果使用 “wrap_content” 和 “match_parent” 尺寸值而不是寫死的尺寸,視圖就會相應地僅使用自身所需的空間或展開以填滿可用空間。此方法可讓布局正确适應各種螢幕尺寸和螢幕方向。

2、 線上性布局中使用weight屬性。

我們可以使用這個屬性來按照比例對界面進行配置設定,完成一些特殊的需求。

關于weight屬性的了解:占用剩餘空間(寬度或高度)的比重。使用這個屬性的時候一般把寬或高的尺寸設定為0dp。

3、 使用相對布局,禁用絕對布局(已經被google完全抛棄)

3.1.2 使用限定符

3.1.2.1 使用尺寸限定符

上面所提到的靈活布局或者是相對布局,可以為我們帶來的優勢就隻有這麼多了。雖然這些布局可以拉伸元件内外的空間以适應各種螢幕,但它們不一定能為每種螢幕都提供最佳的使用者體驗。是以,我們的應用不僅僅隻實施靈活布局,還應該應針對各種螢幕配置提供一些備用布局。

我們可以通過使用配置限定符,在運作時根據目前的裝置配置自動選擇合适的資源了,例如根據各種螢幕尺寸選擇不同的布局。

很多應用會在較大的螢幕上實施“雙面闆”模式,即在一個面闆上顯示項目清單,而在另一面闆上顯示對應内容。平闆電腦和電視的螢幕已經大到可以同時容納這兩個面闆了,但手機螢幕就需要分别顯示。是以,我們可以使用以下檔案以便實施這些布局:

請注意第二種布局名稱目錄中的 large 限定符。系統會在屬于較大螢幕(例如 7 英寸或更大的平闆電腦)的裝置上選擇此布局。系統會在較小的螢幕上選擇其他布局(無限定符)。

3.1.2.2 使用最小寬度限定符

values-sw<N>dp

最小寬度限定符可讓您通過指定某個最小寬度(以 dp 為機關)來定位螢幕。例如,标準 7 英寸平闆電腦的最小寬度為 600 dp,是以如果您要在此類螢幕上的使用者界面中使用雙面闆(但在較小的螢幕上隻顯示清單),您可以使用上文中所述的單面闆和雙面闆這兩種布局,但您應使用 sw600dp 指明雙面闆布局僅适用于最小寬度為 600 dp 的螢幕,而不是使用 large 尺寸限定符。

也就是說,對于最小寬度大于等于 600 dp 的裝置,系統會選擇 layout-sw600dp/main.xml(雙面闆)布局,否則系統就會選擇 layout/main.xml(單面闆)布局。

但 Android 版本低于 3.2 的裝置不支援此技術,原因是這些裝置無法将 sw600dp 識别為尺寸限定符,是以我們仍需使用 large 限定符。

3.1.2.3 使用布局别名

最小寬度限定符僅适用于 Android 3.2 及更高版本。是以,如果我們仍需使用與較低版本相容的概括尺寸範圍(小、正常、大和特大)。例如,如果要将使用者界面設計成在手機上顯示單面闆,但在 7 英寸平闆電腦、電視和其他較大的裝置上顯示多面闆,那麼我們就需要提供以下檔案:

l res/layout/main.xml: 單面闆布局

l res/layout-large: 多面闆布局(低版本)

l res/layout-sw600dp: 多面闆布局(3.2+高版本)

後兩個檔案是相同的,因為其中一個用于和 Android 3.2 +裝置比對,而另一個則是為使用較低版本 Android 的平闆電腦和電視準備的。

要避免平闆電腦和電視的檔案出現重複(以及由此帶來的維護問題),可以使用别名檔案。例如,您可以定義以下布局:

u res/layout/main.xml,單面闆布局

u res/layout/main_twopanes.xml,雙面闆布局

然後添加下面兩個檔案:

以上兩個檔案的内容相同,但它們并未實際定義布局。它們隻是将 main 設定成了 main_twopanes 的别名。由于這些檔案包含 large 和 sw600dp 選擇器,是以無論 Android 版本如何,系統都會将這些檔案應用到平闆電腦和電視上(版本低于 3.2 的平闆電腦和電視會比對 large,版本高于 3.2 的平闆電腦和電視則會比對 sw600dp)。

3.1.2.4 使用螢幕方向限定符

某些布局會同時支援橫向模式和縱向模式,但我們可以通過調整優化其中大部分布局的效果。

port:縱向裝置 (寬小于高)

land:橫向裝置 (寬大于高)

如果使用者旋轉螢幕,這個限定能夠在應用程式運作期間改變。

使用方法和上面的限定符類似。

3.1.3 使用9宮格圖檔(.9.png)

支援各種螢幕尺寸通常意味着您的圖檔資源還必須能适應各種尺寸。例如,無論要應用到什麼形狀的按鈕上,按鈕背景都必須能适應。

如果在可以更改尺寸的元件上使用了簡單的圖檔,您很快就會發現顯示效果多少有些不太理想,因為系統會在運作時平均地拉伸或收縮您的圖檔。解決方法為使用自動拉伸位圖,這是一種格式特殊的 PNG 檔案,其中會指明可以拉伸以及不可以拉伸的區域。

.9的制作,實際上就是在原圖檔上添加1px的邊界,然後按照我們的需求,把對應的位置設定成黑色線,系統就會根據我們的實際需求進行拉伸。

修改.9圖檔可以用Android自帶的工具:sdk oolsdraw9patch.bat

3.1.4 支援多種螢幕密度

由于各種螢幕的像素密度都有所不同,是以相同數量的像素在不同裝置上的實際大小也有所差異,這樣使用像素定義布局尺寸就會産生問題。是以,請務必使用 dp 或 sp 機關指定尺寸。dp 是一種非密度制約像素,其尺寸與 160 dpi 像素的實際尺寸相同。sp 也是一種基本機關,但它可根據使用者的偏好文字大小進行調整(即尺度獨立性像素),是以我們應将該測量機關用于定義文字大小。

但是有些時候,dp也會出現問題:

例如:下面的布局

Nexus 5預覽情況: Nexus one預覽情況:

可以看到中Nexus one上面兩個按鈕發生了重疊。

我們都已經用了dp了,為什麼會出現這種情況呢?

雖然說dp可以去除不同像素密度的問題,使得1dp在不同像素密度上面的顯示效果相同,但是還是由于Android螢幕裝置的多樣性,如果使用dp來作為度量機關,并不是所有的螢幕的寬度都是相同的dp長度,比如說,Nexus S和Nexus One屬于hdpi,螢幕寬度是320dp,而Nexus 5屬于xxhdpi,螢幕寬度是360dp,Galaxy Nexus屬于xhdpi,螢幕寬度是384dp,Nexus 6屬于xxxhdpi,螢幕寬度是410dp。是以說,光Google自己一家的産品就已經有這麼多的标準,而且螢幕寬度和像素密度沒有任何關聯關系,即使我們使用dp,在320dp寬度的裝置和410dp的裝置上,還是會有90dp的差别。當然,我們盡量使用match_parent和wrap_content,盡可能少的用dp來指定控件的具體長寬,再結合上權重,大部分的情況我們都是可以做到适配的。

http://screensiz.es/phone

螢幕密度倍數關系:

3.4 最佳實踐

1、關于高清設計圖尺寸

Google官方給出的高清設計圖尺寸有兩種方案,一種是以mdpi設計,然後對應放大得到更高分辨率的圖檔,另外一種則是以高分辨率作為設計大小,然後按照倍數對應縮小到小分辨率的圖檔。

根據經驗,我更推薦第二種方法,因為小分辨率在生成高分辨率圖檔的時候,會出現像素丢失,我不知道是不是有方法可以阻止這種情況發生。

而分辨率可以以1280*720或者是1960*1080作為主要分辨率進行設計。

設計師用1080x1920(XXHDPI)(9 * 16)做設計,提供一套XXHDPI切圖資源。其他密度不需要提供,讓系統自适配。魅族那種變态分辨率不在考慮之列。

2、ImageView的ScaleType屬性

設定不同的ScaleType會得到不同的顯示效果,一般情況下,設定為centerCrop能獲得較好的适配效果。

3、動态設定

有一些情況下,我們需要動态的設定控件大小或者是位置,比如說popwindow的顯示位置和偏移量等,這個時候我們可以動态的擷取目前的螢幕屬性,然後設定合适的數值。

動态設定螢幕屬性:

public class ScreenSizeUtil {

public static int getScreenWidth(Activity activity) {

return activity.getWindowManager().getDefaultDisplay().getWidth();

}

public static int getScreenHeight(Activity activity) {

return activity.getWindowManager().getDefaultDisplay().getHeight();

}

}

轉載請注明本文位址: Android 螢幕适配方案(七)