Android Training學習筆記之適配不同的設備

Android是一個開源的開放的操作系統,世界上的任何人都可以基於這個系統進行適合自己的定製活動。Android的這樣一個特點使得android世界的碎片化很嚴重,形形色色的android設備太多太多。這就給app開發帶來了不小的困難,保證app在不同的設備上的使用體驗是一致的是每一個開發者必須考慮,但是很頭疼的問題。Google在這塊也做了很多的工作,尤其是在最新的android 6.0中,多設備的支持和自適應做的已經非常好了。要想讓你的app能夠利用google提供的優良自適應特性,你必須要遵守一些google的基本規範。google在training中給出了他的規範:
https://developer.android.com/training/basics/supporting-devices/index.html
這個規範一共分爲3個部分:

  1. 支持不同的語言
  2. 支持不同屏幕的設備
  3. 支持不同系統版本的設備

接下來我們就簡單學習一下google的基本規範。

1. 支持不同的語言

Android作爲一個全球化的操作系統,android會運行在世界上任何一個國家,那麼android的用戶所使用的語言就是非常多樣的。爲了支持不同國家的語言,android提供了string resource機制,具體的做法就是:你應該在你的項目源碼目錄下的res目錄(也就是你的app的resource目錄)中,新建上衆多這樣格式的目錄:

values-<ISO 639-1 locale codes>

然後在這個目錄下面新建名爲strings.xml的文件,這個文件中所有的tag都是以string開始,然後指定一個名字,最後指定一個對應的值:

<string name="app_name">HelloWorld</string>

這裏需要說明一下,上面提到的ISO 639-1 locale codes是國際之間關於國家地區語言代碼的ISO全球統一規範,當然android就是遵守這個的。關於ISO 639-1 locale codes規範的簡介可以查看維基百科的介紹:
https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
全面的介紹可以查看ISO官網的spec:
http://www.iso.org/iso/home/standards/language_codes.htm
如果你的app支持多國語言的話,那麼你的string資源目錄可能有點像下面這個樣子:

MyProject/
    res/
       values/
           strings.xml
       values-es/
           strings.xml
       values-fr/
           strings.xml

這個例子中支持了默認的語言支持(當找不到支持的語言資源的時候,默認使用這個,一般爲英語),西班牙語支持,法語支持。以下是默認語言支持的示例:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">My Application</string>
    <string name="hello_world">Hello World!</string>
</resources>

這是西班牙語支持示例:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mi Aplicación</string>
    <string name="hello_world">Hola Mundo!</string>
</resources>

這是法語支持示例:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="title">Mon Application</string>
    <string name="hello_world">Bonjour le monde !</string>
</resources>

是的,就是這麼簡單,你只要在不同的目錄下的strings.xml中定義上相同name不同語言翻譯的string後,android系統就可以根據當前系統的語言來決定顯示什麼文字了!
我們使用這些string資源基本有兩種方式:在java代碼中使用和在xml等文件中使用,我們先看下再java代碼中怎麼使用:
來自google的例子

// Get a string resource from your app's Resources
String hello = getResources().getString(R.string.hello_world);

// Or supply a string resource to a method that requires a string
TextView textView = new TextView(this);
textView.setText(R.string.hello_world);

在xml文件中使用:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />

2. 支持不同的屏幕

基於android系統的設備是如此之多,從小屏幕的智能手錶到日常使用的智能手機,在從汽車上的智能車載到大屏幕的智能電視。屏幕的尺寸和分辨率是我們開發中必須要考慮的一個問題,同語言國際化一樣,這塊google也有自己的規範。
首先說明一下目前的屏幕尺寸和畫面清晰度的分類:
四種屏幕尺寸:small(小), normal(中), large(大), xlarge(超大)
五種屏幕清晰度(細膩度):low(ldpi)低, medium(mdpi)中, high(hdpi)高, extra high(xhdpi)超高, extra extra high(xxhdpi)極高
這裏需要額外說明一下,從android 3.2(api level 13)開始,上面4種屏幕尺寸已經不建議使用了,取而代之的是一種根據可用屏幕寬度管理屏幕尺寸的新技術。
通常來講以上的幾種屏幕尺寸和清晰度定義基本如下
來自google的圖片
更多關於屏幕尺寸和清晰度的信息請參考google的說明:
https://developer.android.com/guide/practices/screens_support.html
在支持屏幕大小的方面,基本有兩個問題:一是界面佈局,而是圖片顯示大小。先說說界面佈局問題,界面的佈局和屏幕的尺寸關係比較大,如一個比較的大的屏幕尺寸和一個小的屏幕尺寸每屏顯示的內容肯定不一樣,大一點的屏幕可以顯示多一點的內容,佈局可以更加自由一些,小一點的屏幕顯示的內容就比較少,界面元素佈局就會相對緊湊一些。和支持多語言一樣,在支持多屏幕尺寸上,我們也可以使用不同目錄,同樣文件名,不同佈局內容的策略讓android系統根據實際情況決定佈局。我們可以在res目錄下的layout目錄建立這樣的目錄:

layout-<screen size pattern>

這裏的screen size pattern可以是這樣的:

land(表示橫屏)
large(表示大屏)
large-land(表示大屏橫屏)

也就是說你的目錄可能會像這個樣子:

MyProject/
    res/
        layout/              # default (portrait)
            main.xml
        layout-land/         # landscape
            main.xml
        layout-large/        # large (portrait)
            main.xml
        layout-large-land/   # large landscape
            main.xml

但是,上面也提到了,這個技術在android 3.2之後就不需要使用了,因爲android可以使用新技術來定義屏幕尺寸:
https://developer.android.com/guide/practices/screens_support.html#DeclaringTabletLayouts
除了界面佈局的問題,還有的就是app中圖片的顯示問題。不同的分辨率,清晰度去顯示同一張圖片肯定會有問題的,圖片通常會有變形的問題。同樣地,這個問題我們可以按照不同目錄,同一個文件名的方式來處理這個問題。我們可以在res目錄下建立這樣的目錄:

drawable-<density>

這裏的density就是上面提到了幾種,因此如果你的app支持不同清晰度的顯示,那麼你的圖片資源目錄可能像這樣:

MyProject/
    res/
        drawable-xhdpi/
            awesomeimage.png
        drawable-hdpi/
            awesomeimage.png
        drawable-mdpi/
            awesomeimage.png
        drawable-ldpi/
            awesomeimage.png

任何時候你都可以通過@drawable/awesomeimage的方式去使用這個圖片,系統會根據當前設備的清晰度自動選擇相應的圖片顯示。另外,不同清晰度之間的比例是這樣的:

  1. xhdpi: 2.0
  2. hdpi: 1.5
  3. mdpi: 1.0 (baseline)
  4. ldpi: 0.75

也就是說,xhdpi是mdpi圖片尺寸的2倍,如果xhdpi的尺寸是200*200的話,你的mdpi照片就是100*100.同時需要注意的是,低清晰度的圖片不是必須的,當你制定了高清晰度的時候,如果設備是低清晰度的話,那麼系統會自動按照這個比例縮放你的照片。不過,最好還是指定這樣的圖片,不然縮放的過程可能增加額外的內存和cpu消耗,並且縮放的效果不一定是你最想要的。圖片資源中比較重要的可能就是app的icon的設計了,這個是app的門面,這部分的設計可以參考google的文檔:
https://developer.android.com/design/style/iconography.html

3. 支持不同的系統版本

Android是一個快速演變的操作系統,可以看到google的發佈更新頻率是非常快的,android也在以一個非常快的速度進化着。在快速的版本演化中,有一個問題就是新舊的api版本兼容性的問題。老版本的api的可能早就廢棄不用了,新版本的api提供了很好的特性但是很多設備部支持。在創建app的初始,就是決定app的目標平臺和最低平臺,google的建議是至少覆蓋90%的設備用戶。
爲了讓我們的app的能夠正常良好地運行在不同版本上,我們需要在AndroidManifest中指定相應的版本問題。我們使用標籤制定相應版本,目前可以制定的版本有:
minSdkVersion(最小版本)
targetSdkVersion(目標版本)
maxSdkVersion(最大版本)
其中我們一般制定最小版本和目標版本,最小版本指定你的app必須運行的版本,目標版本指定你的app運行的最理想的版本。這個部分在AndroidManifest中指定方式如下:

<uses-sdk android:minSdkVersion="integer"
          android:targetSdkVersion="integer"
          android:maxSdkVersion="integer" />

每個值都是一個int型的無符號數字,這個數字是android的api level。關於android的api level可以參考下面這個表格(來自google)
這裏寫圖片描述
我們要填寫的就是這表格中的API level中的數字。更多信息,參考:
https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels
爲了獲得更加靈活的操作方式,我們還可以在運行時判斷當前系統的版本,方式如下:

private void setUpActionBar() {
    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
    }
}

就是使用Build類的常量判斷,Build類包含了當前系統中的衆多信息,包括cpu類型,設備名稱,製造商,序列號等等信息,更多信息參考Build的api doc:
https://developer.android.com/reference/android/os/Build.html
這裏再囉嗦一句,當系統解析xml資源文件的時候,android會自動過濾掉不識別或者不支持的特性。比如說,你在xml文件中使用了ActionBar這個元素,但是這個元素是android 3.0以上的版本才能支持的,如果是一個低於3.0版本的設備來解析這個xml文件的話,會自動忽略這個元素,而不會產生任何錯誤。
除了以上提到的內容,android在界面效果上還有一些有關係統版本之間的內容。對於每個android版本,沒有版本都會有自己的style和theme,也就是風格和主題。比如說2.3版本的風格和4.0的界面風格就是有很大的不同,4.0的風格更加時尚;5.0之後的風格和主題就發生更大的變化了,因爲引入了“原質化設計(material design)”,使得界面更加自然淳樸。使用這些內置的風格和主題可以使得你的app再不同版本的系統中以一種和系統版本相適應的風格方式顯示。目前google自定了很多風格和主題,可以在以下的鏈接中看到完整的內容:
風格和主題的介紹:
https://developer.android.com/guide/topics/ui/themes.html
系統內置風格:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/styles.xml
系統內置主題:
https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/themes.xml
我們比較常見的有:
對話框主題:

<activity android:theme="@android:style/Theme.Dialog">

透明背景:

<activity android:theme="@android:style/Theme.Translucent">

當然,我們也可以仿造上面系統預定義的方式,自定義風格和主題,定義的內容一般寫在res/values/styles.xml中,這裏是一個例子:

<style name="CodeFont">
     <item name="android:layout_width">fill_parent</item>
     <item name="android:layout_height">wrap_content</item>
     <item name="android:textColor">#00FF00</item>
     <item name="android:typeface">monospace</item>
</style>

當然我們也可以繼承自系統預定義的風格主題,使用parent關鍵字,比如:

<style name="CodeFont" parent="@android:style/TextAppearance.Medium">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>

我們把上面的CodeFont風格繼承自系統的TextAppearance.Medium風格了。更多的信息可以參考:
https://developer.android.com/guide/topics/ui/themes.html#DefiningStyles
我們使用主題或者風格的方式比較簡單,如果相對某個activity應用主題風格可以這樣:

<activity android:theme="@style/CustomTheme">

如果想對整個應用也就是所有的activity應用的話,可以這樣:

<application android:theme="@style/CustomTheme">

關於風格和主題更加詳細的資料,可以看看這個,解釋的還是比較到位的(英文的,嘿嘿):
http://docs.appcelerator.com/platform/latest/#!/guide/Android_Themes

發佈了89 篇原創文章 · 獲贊 110 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章