Androidアプリ開発::Densityの話
前回のエントリで使ったアプリと関連します。なんでIS03では表示したドロイドがePadよりも大きな(ピクセル数的に)表示になってしまったのかってこと。Androidはスケーラブル、って表現が正しいのかわかんないけど、そんな設計になってます。どういうことかって言うと、どんな画面サイズでどんな解像度の端末でも、表示されるモノの物理的な寸法は(ほぼ)同じにしようよってことです。IS03の方が画面が小さく解像度も高いのに、IS03で表示されたドロイドも、ePadで表示されたドロイドも、定規で大きさを測ってみるとほぼ同じになるように表示されてたんです。
その辺の判断の指標になるのが、Density(dpi)です。IS03は320dpi(厳密にはもう少し大きいけど、端末的にそういうことになっているみたい)、ePadは160dpiです。もう少し言うならば、Androidの基準になっているDensityは160dpiです。なので、160dpiの画像しか用意していない場合、もし違うDensityの端末だと、それに合わせて適当に伸縮されてしまいます。つまりIS03だと、縦横二倍に拡大されて読み込まれるんです。
拡大縮小するんではなく、それぞれのDensityに合わせた適切な画像を用意したいって場合は、APIレベル4(Android 1.6)から対応したようです。前述のレベル以上でEclipseプロジェクトを作った場合、resフォルダの中に、
drawable-ldpi
drawable-mdpi
drawable-hdpi
という3つのフォルダができます。それぞれ120dpi、160dpi、240dpiに対応していて、同じ名前でファイルを入れておくと、システムが最適なDensityのファイルを取ってきてくれるという仕組みになってます(単にdrawableという名前のフォルダだと、基準である160dpi扱いになるようです)。ここでもし240dpiの端末で、hdpiのファイルがなかったら、mdpiのファイルを240/160=3/2倍して使われます。
ではIS03ではどうでしょう。320dpiというDensityは該当がありません。試してみたところ、hdpiのものが320/240=4/3倍されていました。hdpiがなければ、mdpiを320/160=2倍して使われます。そこで、適当になんとなく
drawable-xhdpi
というフォルダを作って画像を入れたところ、スケーリングなくドンピシャで表示されました。320dpi端末はxhdpiということのようです。
そこで話は戻りますが、前回のアプリやゲームなどでは、勝手にスケーリングしてくれんなよ、ということは少なくないと思います。全てのフォルダに同じファイルを突っ込んでおくのも手ですが、容量のムダですし、将来的にxhdpiを超えるsxhdpiとかuxhdpiとか、あるいは反対にxldpiとかも出てこないとは限りません。そんな場合には、
drawable-nodpi
というフォルダを作っておくと、その中のファイルは端末Densityによらず、実寸でロードされるようです(API レベル4以上)。
おさらい
API レベル4(Android 1.6)以上では、リソースから画像を読む場合、端末のDensityに合わせて以下のフォルダから画像が選択される。もし該当する画像がない場合は、それ以外のDensityの画像からDensityに合わせて拡大縮小される。
drawable 160dpi
drawable-ldpi 120dpi
drawable-mdpi 160dpi
drawable-hdpi 240dpi
drawable-xhdpi 320dpi
drawable-nodpi Density非依存
ちなみにIS03は、APIレベル3のアプリからだと、HVGA(320x480)のmdpi端末と認識されます。こういう状況であれば、Android 1.5は切り捨てちゃおーぜ、というのは仕方がないかもしれませんね。ePad選択時にAndroid 1.6を基準にしておいて正解だったかな。
その辺の判断の指標になるのが、Density(dpi)です。IS03は320dpi(厳密にはもう少し大きいけど、端末的にそういうことになっているみたい)、ePadは160dpiです。もう少し言うならば、Androidの基準になっているDensityは160dpiです。なので、160dpiの画像しか用意していない場合、もし違うDensityの端末だと、それに合わせて適当に伸縮されてしまいます。つまりIS03だと、縦横二倍に拡大されて読み込まれるんです。
拡大縮小するんではなく、それぞれのDensityに合わせた適切な画像を用意したいって場合は、APIレベル4(Android 1.6)から対応したようです。前述のレベル以上でEclipseプロジェクトを作った場合、resフォルダの中に、
drawable-ldpi
drawable-mdpi
drawable-hdpi
という3つのフォルダができます。それぞれ120dpi、160dpi、240dpiに対応していて、同じ名前でファイルを入れておくと、システムが最適なDensityのファイルを取ってきてくれるという仕組みになってます(単にdrawableという名前のフォルダだと、基準である160dpi扱いになるようです)。ここでもし240dpiの端末で、hdpiのファイルがなかったら、mdpiのファイルを240/160=3/2倍して使われます。
ではIS03ではどうでしょう。320dpiというDensityは該当がありません。試してみたところ、hdpiのものが320/240=4/3倍されていました。hdpiがなければ、mdpiを320/160=2倍して使われます。そこで、適当になんとなく
drawable-xhdpi
というフォルダを作って画像を入れたところ、スケーリングなくドンピシャで表示されました。320dpi端末はxhdpiということのようです。
そこで話は戻りますが、前回のアプリやゲームなどでは、勝手にスケーリングしてくれんなよ、ということは少なくないと思います。全てのフォルダに同じファイルを突っ込んでおくのも手ですが、容量のムダですし、将来的にxhdpiを超えるsxhdpiとかuxhdpiとか、あるいは反対にxldpiとかも出てこないとは限りません。そんな場合には、
drawable-nodpi
というフォルダを作っておくと、その中のファイルは端末Densityによらず、実寸でロードされるようです(API レベル4以上)。
おさらい
API レベル4(Android 1.6)以上では、リソースから画像を読む場合、端末のDensityに合わせて以下のフォルダから画像が選択される。もし該当する画像がない場合は、それ以外のDensityの画像からDensityに合わせて拡大縮小される。
drawable 160dpi
drawable-ldpi 120dpi
drawable-mdpi 160dpi
drawable-hdpi 240dpi
drawable-xhdpi 320dpi
drawable-nodpi Density非依存
ちなみにIS03は、APIレベル3のアプリからだと、HVGA(320x480)のmdpi端末と認識されます。こういう状況であれば、Android 1.5は切り捨てちゃおーぜ、というのは仕方がないかもしれませんね。ePad選択時にAndroid 1.6を基準にしておいて正解だったかな。
スポンサーサイト
