前回のsw<N>dpで記載した"アプリ描画領域"について、もう一歩踏み込んで調査します。
<N>値にはレイアウトに最低限必要なサイズを指定します。
もし、<N>値に画面解像度の一辺(幅or高さ)を指定する場合は下記の点に注意しなければ
いけません。
<N>に指定する値は"アプリが利用できる画面領域"であり"解像度の一辺(幅or高さ)"では
ありません。
例えば、画面解像度が480px×800pxで画面密度がmdpiの端末をターゲットにした場合。
values-h800dpのリソースフォルダを用意すれば、システムがこれを参照することを期待
するかもしれませんが、おそらくこれは参照されません。
なぜなら、解像度で800dpが確保されていてもステータスバーやナビゲーションバーの領域が
アプリが利用できる画面領域を削るので、ほとんどの場合で解像度よりも小さな値となる
からです。
下記の設定値を持つ端末とリソースで動作確認してみます。
【エミュレータA:ナビゲーションバーなし】
・解像度:480×800
・画面密度:mdpi(160dpi)
・ステータスバーの高さ:25dp
・ハードキー:搭載
【エミュレータB:ナビゲーションバーあり】
・解像度:480×800
・画面密度:mdpi(160dpi)
・ハードキー:非搭載
・ステータスバーの高さ:25dp
・ナビゲーションバーの高さ:48dp
【リソース】
下記のリソースを持つ.apkを作成
res/values-h727dp/*
res/values-h775dp/*
res/values-h800dp/*
端末の解像度はどれも480×800です。
しかし、values-h800dpがリソースとして選択されることはありません。
これは、ステータスバー領域がアプリが利用できる領域を25dp削っているからです。
エミュレータAでは、ステータスバー領域分の25dpを削った残りが、アプリ描画領域(775dp)
になるのでvalues-h775dpのリソースが参照されます。
しかし、エミュレータBではh775dpのリソースは参照されません。
これは、エミュレータBがナビゲーションバーを表示しており、更に48dp削られるからです。
そのため、エミュレータBではvalues-h727dpのリソースが参照されます。
x<N>dpが導入された経緯や目的を考えれば正しい動作と言えます。
●ナビゲーションバーとアプリ描画領域
Android4.0ではナビゲーションバー領域を新設し、バック、ホームおよび最近使用したアプリを
表示するための仮想ボタンをここに表示しています。
Android4.0では ナビゲーションバー は必ず表示されるというわけではありません。
バックやホームなどのボタンをハードキーとして備えている端末では、ナビゲーションバー
の存在は冗長なのでこれをシステム側で非表示に設定します。
ナビゲーションバーはWindowManagerから取得できるDisplayMetrics値に影響します。
例えば、下記のような解像度を取得するコードはよく目にします。
DisplayMetrics metrics = new DisplayMetrics(); this.getWindowManager().getDefaultDisplay().getMetrics(metrics); Log.d("yuki", "widthPixels=" + metrics.widthPixels); Log.d("yuki", "heightPixels=" + metrics.heightPixels);
metrics.widthPixels, metrics.heightPixelsの戻り値は ナビゲーションバー の有無で
下記のように変化します。
【ナビゲーションバー無】
widthPixels=480px
heightPixels=800px
【ナビゲーションバー有】
widthPixels=480px
heightPixels=752px
DisplayMetrics値がナビゲーションバーの高さ分の影響を受けていることが分かります。
端末のスペックにある解像度とDisplayMetrics値で得られる解像度に差異が出るというこ
とです。
以上です。