2012年5月2日 星期三

[UI] Supports Multiple Screen - Scaling

If layout is dependency on pixel...
  • mdpi -> ldpi: 圖會變大而失真
  • mdpi -> hdpi: 圖會變小 (因為 pixel 變多/ inch)
  • 也因此在 ldpi mdpi hdpi 上會顯得大小不一

但若是採用 independency methods...
  • 則系統會選擇不同的 resource 所以如果只有 mdpi:
    • 則會縮小顯示在 ldpi device 上
    • 則會放大顯示在 hdpi device 上 而可能失真
  • 最終在 ldpi mdpi hdpi 大小會相同

Multiple screens support
  • Started in Android 1.1
  • Resources management added in 1.5
  • Compatibility mode added in 1.6

Inside Android
  • Everything is pixels
  • Resolution independent units
    • dip and dp
    • pt and sp
    • mm, in
  • Layouts

Resources management
  • Pre-scaling
  • Auto-scaling
  • By default, resources are mdpi
    • res/drawable
  • Use dpi-specific resources
    • res/drawable-hdpi
    • res/drawable-ldpi
    • res/drawable-mdpi


Pre-scaling (android:anydensity="true")
  • 系統善用 resources 的方式。系統會根據裝置 density 去選擇要使用那種大小的圖片(res/drawable-ldpi, drawable-mdpi, drawable-hdpi...)或者是放大/縮小 default drawable 來符合當下螢幕密度。
  • 如果 application 中沒有相符合的 resources 那麼系統就會使用預設的(res/drawable or res/drawablw-mdpi)並且放大或縮小它來顯示。
    • res/drawable 被視為 baseline screen density (mdpi)。
  • 如果取得已被放大/縮小的圖片的 dimension,那麼值會是已經放大/縮小後的。
  • Examples:
    • for an hdpi device, when there is only mdpi image 100 x 100, then the image will be pre-scaled to 150 x 150;
    • for an mdpi device, when there is only hdpi image 150 x 150, then the image will be pre-scaled to 100 x 100;
  • 此功能預設是 true,如果不想讓圖片被經過這樣的處理或是放大/縮小後顯示,可...
    • 將 resources 放在 res/drawable-nodpi 下。
    • 在 AndroidManifest 中設 <supports-screens android:anydensity="false">。
    • 設定 Bitmap 的 isScaled() 為 false。
    • 當 pre-scaling 被關閉,系統便會在畫圖時縮放圖片(see Auto-scaling),但不建議關閉 pre-scaling。

Auto-Scaling
  • 若想強迫使用 auto-scaling,則是要關閉 pre-scaling,ex: 在 AndroidManifest 中設 <supports-screens android:anydensity="false">。
  • 為了確保在不同裝置上能顯示相同的大小,所以即使 pre-scaling is disable 仍會再畫圖時做 auto-scaling。
  • CPU expensive, but use less memory.
  • Bitmap created at runtime will auto-scaled.


AndroidManifest.xml
  • android:anyDensity: 程序是否可在任何密度的螢幕上執行。主要是為使用了 px 作為單位的圖片。
    • If false: 系統就會 pre-scaling resources/density-compability,根據不同的屏幕密度將 px 值轉換為合理的大小。
    • If true: 就會關閉 pre-scaling resources/density-compability 。
    • 如果程序是以 dp 作為長度單位的,則不會受此值影響。
  • android:xxxScreens: 是否支持某屏幕(physical size)。
    • If false: 表示不支援該大小的螢幕,系統會啟用 size-compability 特性,即只顯示標準屏幕(normal size, mdpi)的大小。
      • ex: 即使是 hdpi 仍以 mdpi 的大小顯示,其餘部份則會留黑。
    • If true: 表示支援該大小的螢幕,系統就不會做任何處理直接顯示。

可以利用下列兩種方式來在程式中相對的長度:

計算出 dipValue 在該螢幕中應該為的 pixel value。
// Convert the dips to pixels
final float scale = getContext().getResources().getDisplayMetrics
().density;
pixels = ( int) (dipValue * scale + 0.5f );
宣告 dip 在 resources values 中,再取出該 pixel size by getDimensionPixelSize()

    20dip 

Resources r = aContext.getResources();
int length = r.getDimensionPixelSize(R.dimen.length);


* Reference
- 2009_Android_resolution_independence_and_high_performance_graphics_RomainGuy ***
Supporting Multiple Screens
- Situee's Blog - iPhone,Technology: Pre-scaling, Auto-Scaling and Screen Density
- How to Support Multiple Screens in Android without the need to Provide different bitmap drawables for different screen densities
- Android Samsung S I9000 screen size and density issues
- Android 屏幕兼容性
- Android ApiDemos示例解析(63):Graphics->Density (上)  ***
- Android ApiDemos示例解析(63):Graphics->Density (下)  ***
- android应用 DPI不同的适配问题分析 **

沒有留言:

張貼留言