2012年10月8日 星期一

[AndroidDev] Supporting Multiple Screens

Android system 用以下方式使得你 App 不因螢幕密度有所改變 (density independence):
  • Scales dp units as appropriate for the current screen density
    • Use wrap_content, fill_parent, or dp units when specifying dimensions in an XML layout file
    • Do not use hard coded pixel values in your application code
    • Do not use AbsoluteLayout (it's deprecated)
  • Scales drawable resources to the appropriate size, based on the current screen density, if necessary.
    • Supply alternative bitmap drawables for different screen densities
=> Android System 依據 screen size/density 調整 layout;依據 screen density 調整 bitmap drawables。


How to Support Multiple Screens
  • Explicitly declare in the manifest which screen sizes your application supports
    • 宣告 <supports -screens="-screens"> 以避免你的 app 被從 google play 下載到不合的裝置。
    • 但當運作在較大的螢幕上時會影響 screen compatibility mode 的運作。
  • Provide different layouts for different screen sizes
    • 提供不同 layout for 不同螢幕大小,利用空間及便於 user 操作。
    • ex: small, normal, large, and xlarge。
    • 但是在 Android 3.2 (API level 13) 以上 screen size groups are deprecated,應改使用 sw-dp configuration qualifier。
  • Provide different bitmap drawables for different screen densities
    • 提供不同大小的圖片資源。
    • ex: ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high)。
    • 假如只提供預設大小 (drawable, mdpi),那麼圖片在 hdpi 被放大,ldpi 縮小。

系統選擇 resources 的方式

  • The system uses the appropriate alternative resource
    • 依據螢幕 size and density 和你所提供的 resources 及所設定的 qualifier 對應出最適合的 resources,無則使用預設放大縮小(ex: drawable)。
    • 但在使用預設前,系統會先找是否能使用其他 density resources 的可能。
    • ex: 若需要 ldpi,但只有 hdpi and mdpi,那麼系統會優先選擇 hdpi 的,因為改變較小,hdpi * 0.5 < mdpi * 0.75。 
  • Eliminate resource files that contradict the device configuration. 
    • 依 qulifier 篩選,刪去不合者,但 Screen pixel density 不合時並不會刪去,Android 會選擇最適合 螢幕密度的(most closely matches the device screen density)。 
    • 有以下 qulifier: 
      • MCC and MNC 
      • Language and region 
      • smallestWidth(Added in API level 13.) 
      • Available width(Added in API level 13.) 
      • Available height(Added in API level 13.) 
      • Screen size(Added in API level 4) 
      • Screen aspect
        • long: Long screens, such as WQVGA, WVGA, FWVGA 
        • notlong: Not long screens, such as QVGA, HVGA, and VGA 
      • Screen orientation 
      • UI mode(Added in API level 8, television added in API 13) 
      • Night mode( Added in API level 8.) 
      • Screen pixel density (dpi) 
      • Touchscreen type Keyboard availability 
        • Primary text input method 
        • Navigation key availability 
        • Primary non-touch navigation method 
      • Platform Version (API level) 
Note: 
  • 選擇 size qualifiers 時,系統會選擇較小 screen size 的資源,
    • ex: large screen size 使用 normal screen size resources。 
  • 但如果只有較大 screen size resources 可用時,則會 crash
    • ex: normal screen size,但只有 large size resource。 
Tip: 
如果不想要被放大縮小,則可將圖片放入 nodpi;沒有 qualifier,是預設仍會放大縮小。


New qualifiers in Android 3.2 
  • 在 Android 3.0 時,要提供給 tablet 使用的 layout 可放入 res/layout-xlarge/,但這樣如果想在 7" 上也使用 tablet layout,則大部份都會不合條件,7" tablet 會和 5" handset 一同屬於 large group,這樣開發者變無法藉 screen size group 讓 7" tablet 能使用不同的 layout,因此在 Android 3.2 有了新的 qualifier,swdp
  • qualifiers 上指定的 size 應該為你畫面呈現時所需要的空間 (activity's window, include action bar),因為 Android System 可能會佔掉些空間 (such as the system bar at the bottom of the screen or the status bar at the top),所以系統是扣除 system UI 後的大小才是有效範圍
利用 qualifier 使用不同資源:
  • Create a new directory in your project's res/ directory and name it using the format:
    • <resources_name>-<qualifier>
      • <resources_name> is the standard resource name.
        • ex: drawable, layout, 
      • <qualifier> is a configuration qualifier.
        • ex:  hdpi, xlarge..
    • 可同時使用多個,用 dash (-) 做為分隔即可。
  • 在該指定的 directory 下放入相對應的 configuration-specific resources,resource 命名需和 default resources 相同,系統才能替代。


Scaling Bitmap objects created at runtime
  • a Bitmap object 系統視其為 mdpi,並且會使用 "auto-scaling"。
    • 若是想建立符合 screen density 的 bitmap,使用 setDensity() 指定是 DisplayMetrics#DENSITY_HIGH, DisplayMetrics#DENSITY_LOW...etc。
    • 如果是透過 BitmapFactory 建立 bitmap (ex: from a file or a stream),使用 BitmapFactory.Options 去設定屬性,做為系統是否 scale it 的參考,ex:
      • inDensity: 設定 bitmap density。
      • inScaled: 指定 bitmap 是否縮放以符合 screen size。如果設為 false,則表示關閉 pre-scaling 功能,那麼系統則會 auto-scale it at draw time。
  • auto-scale 會比 pre-scaling 花費較多 CPU 資源但較節省 memory 空間。
Note:
In Android 3.0 and above, there should be no perceivable difference between pre-scaled and auto-scaled bitmaps, due to improvements in the graphics framework.


To summarize, you should be sure that your application layout: 
  • Fits on small screens (so users can actually use your application) 
  • Is optimized for bigger screens to take advantage of the additional screen space 
  • Is optimized for both landscape and portrait orientations 



* Reference
- Supporting Multiple Screens | Android Developers
- Providing Resources | Android Developers

沒有留言:

張貼留言