2012年9月26日 星期三

[AndroidDev] New resources selector (>= API 3.2)

Screen density dpi (dots per inch)
ex: 相同 physical area "low" density 會比 a "low" density screen "normal" or "high" density screen 較少 pixel。

dp (density-independent pixel)
  • The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen
  • The baseline density assumed by the system for a "medium" density screen (160 dpi).
  • px = dp * (dpi / 160)
    • ex: on a 240 dpi screen, 1 dp equals 1.5 physical pixels.
  • scaling ratio
    • 3(ldpi) : 4(mdpi) : 6(hdpi) : 8(xhpi)
    • ex: 480 x 800 hdpi/1.5 -> 320 x 533 mdpi in dp's

Screen size
  • Supported from 1.6.
  • 是系統依照 pixel and density 去算出長寬的 dp 然後對應所得。
  • Resolustion convert to dp presentaion of mdpi and decide its size (small, ..)。
  • 分類:
    • xlarge screens are at least 960dp x 720dp. (>= 2.3)
      • approximately-10” tablets, ex: Motorola Xoom
    • large screens are at least 640dp x 480dp.
      • ex: Dell Streak and original 7” Samsung Galaxy Tab
    • normal screens are at least 470dp x 320dp.
    • small screens are at least 426dp x 320dp.
      • Android does not currently support screens smaller than this.
  • 將裝置 dpi 轉至 mdpi,對應上表,長寬最接近且不小於標準之分類。ex:
    • A QVGA screen is 320x240 ldpi.
      • ldpi * 4/3 = mdpi
      • Result: 426dp x 320dp => small
    • The Xoom is a typical 10” tablet with a 1280 x 800 mdpi screen.
      • Result: 1280 x 800 => xlarge
    • The Dell Streak is a 800 x 480 mdpi screen.
      • Result: 800 x 480 => large
    • A typical 7” tablet has a 1024 x 600 mdpi screen.
      • Result: 1024 x 600 => large
      • But!! Exception "Samsung Galaxy Tab"
      • Samsung Galaxy Tab 1024 x 600 7” 應該是為 large,但因為 device configure 視為 hdpi 所以 hdpi * 2/3 = mdpi => 682dp x 400dp => normal!! 所以它應該是 large 但系統會將其視為 normal。
      • This was a mistake in the framework’s computation of the size for that device that we made. Today no devices should ship like this....

新增於 3.2 的屬性:
  • width dp
    • 現在螢幕方向的寬(dp),也就是當方向改變,寬也會隨之改變。
    • the current width available for application layout in “dp” units; changes when the screen switches orientation between landscape and portrait.
  • height dp
    • 現在螢幕方向的高(dp),也就是當方向改變,寬也會隨之改變。
    • the current height available for application layout in “dp” units; also changes when the screen switches orientation.
  • smallest width dp
    • 螢幕高與寬的最小值,此值固定,不會因為螢幕方向改變而改變。
    • the smallest width available for application layout in “dp” units; this is the smallest width dp that you will ever encounter in any rotation of the display.

Typical numbers for screen width dp are:
  • 320
    • a phone screen 
    • 240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi, etc
  • 480
    • a tweener tablet like the Streak 480 x 800 mdpi
  • 600
    • a 7” tablet 
    • 600 x 1024
  • 720
    • a 10” tablet
    • 720 x 1280, 800 x 1280, etc


Resources Selector Examples

限定使用資源的最小寬度(smallest-width),如下:
res/layout/main_activity.xml           # For phones
res/layout-sw600dp/main_activity.xml   # For 7” tablets
res/layout-sw720dp/main_activity.xml   # For 10” tablets
Android 會選擇最接近但不大於的自身寬度的資源,如 700dp x 1200dp tablet 會使用 layout-sw600dp 裡的資源。


限定使用資源的寬度(width),假設你想直向時只顯示某區塊,而橫向時因為寬度較大,想顯示多點內容,可以使用這方式,如下:
res/layout/main_activity.xml          # Single-pane
res/layout-w600dp/main_activity.xml   # Multi-pane when enough width

smallest width < 600 時使用 layout; 大於 600 則會依據方向所在的寬使用 layout-sw600dp 或 layout-sw600dp-w720dp:
res/layout/main_activity.xml                 # For phones

res/layout-sw600dp/main_activity.xml         # Tablets

res/layout-sw600dp-w720dp/main_activity.xml  # Large width



// 或是寫成 layout-sw600dp-port,表示直向時使用此

res/layout/main_activity.xml                 # For phones

res/layout-sw600dp/main_activity.xml         # Tablets

res/layout-sw600dp-port/main_activity.xml    # Tablets when portrait


和舊的 qualifier 一同使用,如下:
// 使用 layout-swNNNdp 比 layout-port 好
res/layout/main_activity.xml                 # For phones
res/layout-land/main_activity.xml            # For phones when landscape
res/layout-sw600dp/main_activity.xml         # Tablets


相容性寫法

Type 1 - Using new qualifiers with old qualifiers
new qualifiers(ex: layout-sw600dp) 會被舊版本忽略,所以以下寫法能 work:
res/layout/main_activity.xml           # For phones
res/layout-xlarge/main_activity.xml    # For pre-3.2 tablets
res/layout-sw600dp/main_activity.xml   # For 3.2 and up tablets

Type 2 - Using new qualifiers with old qualifiers for different layouts
利用 values selector 使用相同名稱指向不同 layout:

res/layout/main_activity.xml           # For phones
res/layout/main_activity_tablet.xml    # For tablets


res/values-xlarge/layout.xml
res/values-sw600dp/layout.xml

res/values-sw600dp/layout.xml:

    
            @layout/main_activity_tablet
    


Type 3 - Select in code
在程式中判斷螢幕大小決定 layout:
public class MyActivity extends Activity {
    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate();

        Configuration config = getResources().getConfiguration();
        // config.smallestScreenWidthDp: >= API 3.2
        if (config.smallestScreenWidthDp >= 600) {
            setContentView(R.layout.main_activity_tablet);
        } else {
            setContentView(R.layout.main_activity);
        }
    }
}


* Reference
- Android Developers Blog: New Tools For Managing Screen Sizes
- Supporting Multiple Screens

沒有留言:

張貼留言