dpとは?
Androidのデザインにおいて、必ず理解しておくべきポイントのひとつがdpについてです。
dp(density-independent pixels)とは密度非依存ピクセルのことで、dipとも呼ばれています。
Androidはこのdpのおかげで多用な端末をサポートできているのです。
dpのある世界 - 端末の解像度が違っても表示サイズは保たれる
Supporting Multiple Screens | Android Developers
More Resource Types | Android Developers
px、dpi、dp
dpを理解する上で欠かせない要素がpx(ピクセル)とdpi(画面密度)です。
px
px(pixel)というのはハードウェアで実装されている解像度そのものです。ピクセルとも言います。
Androidでは端末によって画面解像度が大きく異なる場合があるため、pxで要素を表示すると端末の画面解像度に応じて表示される実サイズがまちまちになってしまいます。
Androidアプリ上でピクセルを直接扱う局面は限られており、ほとんどが画像編集とOpenGL関連です。
dpi
dpi(dots per inch)は画面密度のことで、1インチの中に何ドット含まれているかを表しており、そのままScreen Densityと表現されることもあります。
同じフルHD解像度の端末でもスマートフォンとタブレットではこのdpiが異なっているため、Androidではpxとdpiを考慮したdpという単位が必要だったのです。
ただし、実際のdpiは端末ごとに異なるため、個別にサポートするのはあまり現実的ではありません。
そこで、Androidではdpiをある範囲ごとにランク分けすることにしました。
このランク分けされた画面密度は汎用密度(generalized density)と呼ばれています。
Supporting Multiple Screens | Android Developers
Devices and Displays | Android Developers
dp
dp(density-independent pixels)とは密度非依存ピクセルのことで、dipとも呼ばれます。
密度に依存しないピクセルとは、どの画面密度でも同じように表示できるピクセル単位ということです。
dpで指定した値を画面密度に応じて計算することで、実際の端末で表示するpxに変換することができます。
このpxを表示してみるとどの端末でも同じように表示されるため、密度非依存ピクセルと呼んでいるのです。
もちろんここでいう密度とは汎用密度のことなので、実dpiが汎用密度の基準dpiからずれている端末ではわずかに表示サイズに違いが出ます。
汎用密度ではこの問題を考慮し、細かく範囲を設定していますが、「厳密に同じサイズで表示されるわけではない」ということは覚えておく必要があります。
汎用密度とdp、pxの関係は以下のようになっています。
ldpiの倍率が0.75倍なため、dpでの指定は4の倍数を使うのが良いでしょう。
汎用密度 | 倍率 | dp | px |
---|---|---|---|
ldpi | x0.75 | 4dp | 3px |
mdpi | x1 | 4dp | 4px |
hdpi | x1.5 | 4dp | 6px |
xhdpi | x2 | 4dp | 8px |
xxhdpi | x3 | 4dp | 12px |
xxxhdpi | x4 | 4dp | 16px |
sp
dpに似た単位として、sp(scale-independent pixel)があります。
これは文字サイズの指定に用いるもので、画面密度に加えてフォントサイズの設定も考慮されています。
端末のdp解像度
dpの大きな利点のひとつは、端末のdp解像度をある程度絞り込めることです。
汎用密度の範囲は端末の画面サイズをdpで表したときにうまく重なるように設定されているため、ほとんどの端末は一定のdp解像度範囲に収まります。
スマートフォンであれば、横幅は320-410dp
の範囲に収まるとされています。
(以前は384dp
まででしたが、Nexus6追加時に410dp
に拡張されました)
試しに、いくつかのNexus端末を元に計算してみましょう。
端末名 | px解像度 | 汎用密度 | dp解像度 |
---|---|---|---|
Galaxy S | 480 x 800 | hdpi | 320 x 534 |
Galaxy Nexus | 720 x 1280 | xhdpi | 360 x 640 |
Nexus 5 | 1080 x 1920 | xxhdpi | 360 x 640 |
Nexus 6 | 1440 x 2560 | 560dpi | 410 x 730 |
Nexus 5X | 1080 x 1920 | 420dpi | 410 x 730 |
Nexus 6P | 1440 x 2560 | 560dpi | 410 x 730 |
アプリを Nexus 6 と Nexus 9 に備えましょう - Google Developer Japan Blog
Android 6.0 Marshmallow: Nexus 端末へ配信開始 - Google Developer Japan Blog
このように、実解像度の違いに関わらず、dpでみた横幅は6台とも320-410dp
の範囲に収まっていることがわかります。
320-410dp
で崩れないレイアウトを心がけておけばほとんどの端末で崩れることはありません。
最近発売された端末のdp解像度の傾向は以下にまとめてあります。
2014年発売Android端末のdp解像度まとめ - Qiita
2015年発売Android端末のdp解像度まとめ - Qiita
dpと画像
Androidではアイコンなどの画像を利用する際、汎用密度ごとに適切な解像度の画像を用意することが推奨されています。
これらの画像も一旦dpでデザインし、各画面密度に必要なピクセルを計算したほうが良いでしょう。
例として、以下のようなアイコン画像を用意する場合をあげます。
縦横48dp
で上下左右に8dp
ずつの余白を持たせ、内側32dp
をデザイン領域としています。
このアイコンを汎用密度ごとに用意する場合、以下の様にピクセル数が決まります。
汎用密度 | 倍率 | 縦横のサイズ | 上下左右の余白 | デザイン領域のサイズ |
---|---|---|---|---|
ldpi | x0.75 | 36 | 6 | 24 |
mdpi | x1 | 48 | 8 | 32 |
hdpi | x1.5 | 72 | 12 | 48 |
xhdpi | x2 | 96 | 16 | 64 |
xxhdpi | x3 | 144 | 24 | 96 |
xxxhdpi | x4 | 192 | 32 | 128 |
難点
dpではできないこと、難しいこともあります。
Androidでは汎用密度で計算したdpによる画面サイズが端末ごとに大きく変わらないという法則によってレイアウトを行います。
しかし、物理的に極端に小さい端末や汎用密度の基準から極端に外れた端末ではdp換算された画面解像度が大きく異なる場合があります。
イレギュラーな端末なのであまり考慮する必要はありませんが、サポート対象端末選定の際には該当端末のdpiとdp解像度を意識したほうが良いでしょう。
スマートフォンとdp
スマートフォンにおけるdpの注意点やTipsをまとめます。
国内での主流端末の解像度はおもにハーフHD(1280x720)、フルHD(1920x1080)、WQHD(2560x1440)になっており、いずれも360dp x 640dpです。
しかし4インチ台の320dp端末も新機種が発売されており、直近で発売されたNexus端末は410dpを採用しています。
このことから、320-410dp範囲の対応は必須と言えるでしょう。
レイアウトの決め方
前述の通りスマートフォンの画面幅は320-410dp
なので、まず320dp
で配置します。
320dp
で各要素を配置できたら、410dp
の場合にどのようなレイアウトになるかを考えます。
各要素を伸縮させたり余白を広げたりして不自然なレイアウトにならないように工夫しましょう。
このとき、RelativeLayout
を使ったりLinearLayout
のandroid:layout_weight
を使うと自然に対応することができます。
スマートフォンでの横向き表示に対応する場合、横幅が730dp
に達する端末もあるので別レイアウトにするかどうかも考慮したほうが良いでしょう。
詳しくはタブレット対応の項を参照してください。
縦方向については480dp-730dp
におさまる場合が多いですが、横幅と違い端末のアスペクト比によってかなり差があります。
ListView
やGridView
などの縦スクロール要素をうまく使って余白が開きすぎないように調整しましょう。
縦480dp
で見切れないレイアウトであっても画面回転に対応する場合はスクロール領域を入れておくべきです。
##よくある工夫
リソースを最小短辺サイズ(sw360dp
など)で分割することにより、短辺があるサイズ以上の端末のみに代替リソースを提供することが出来ます。
最小短辺サイズでリソースを分割する際はなるべくdimenを分割するようにしましょう。
layoutを分割してしまうと、後々管理が大変になりがちです。
タブレットとdp
タブレットにおけるdpの注意点やTipsをまとめます。
国内では最近のタブレットの解像度はアスペクト比16:10の1280x800px
や1920x1200px
、2560x1600px
が主流ですが、画面サイズが大きいためスマートフォンとは汎用密度が異なることに注意する必要があります。
Android Developersによると、dp解像度では短辺が600-800dp
、長辺が960-1280dp
の範囲におさまる想定になっています。
タブレットのdp解像度をいくつか算出してみましょう。
端末名 | px解像度 | 汎用密度 | dp解像度 |
---|---|---|---|
Nexus 7(2012) | 1280 x 800 | tvdpi | 962.4 x 601.5 |
Nexus 7(2013) | 1920x 1200 | xhdpi | 960 x 600 |
Nexus 10 | 2560 x 1600 | xhdpi | 1280 x 800 |
Nexus 9 | 2048 x 1536 | xhdpi | 1024 x 768 |
このようにアスペクト比の異なるNexus 9も含め、全て範囲内におさまりました。
Nexus 7(2012)のtvdpiは x1.33 という倍率を持った特殊な汎用密度です。
通常はmdpiとhdpiのリソースが必要に応じて流用されるため、これを直接ターゲットにして代替リソースを提供することは推奨されていません。
スマートフォンとの違い
タブレットの判定方法は、実は2種類あります。
現在は短辺600dp以上(sw600dp
)という条件が利用されることが多いですが、API Level 13で追加されたフラグのため、これ未満のタブレットでは適用できません。
そのため、画面物理サイズに応じた指定(large/xlarge)を併用する場合があります。
res/layout-xlarge
(API Level 13未満)
res/layout-sw600dp
(API Level 13以降)
ただし、国内では現状API Level 13未満のタブレットがほとんど流通していないため、xlarge設定が必要になる機会はあまりありません。
幅ではなく短辺を使用するのは、単純に幅800dp(w800dp)で判定した場合では縦持ちしたタブレットが含まれず、幅600dp(w600dp)では横向きのスマートフォン端末が含まれる可能性があるためです。
逆に、タブレット、スマートフォンにこだわらずにマルチペインを実装する場合は幅600dp(w600dp)あれば十分という考え方もできます。
レイアウトにあわせた適切な代替リソースの提供を行いましょう。
レイアウトの決め方
まず、タブレット=横画面という思い込みを一旦捨てましょう。
7インチタブレットの短辺600dp
でもスマートフォンと比べるとかなり広いので、タブレットの場合は縦持ちであってもマルチペンレイアウトなどのタブレット向けUIを実装しているアプリは多いです。
また、短辺/長辺でdpの範囲が区別されているとはいえ、10インチタブレット短辺の800dp
は7インチタブレットの長辺960dp
とそこまで大きくかわりません。
おすすめのレイアウト方法のひとつは、すべてのAndroid端末を横幅320dp(または300dp)ごとに分類する方法です。
<integer name="columns">1</integer>
<integer name="columns">2</integer>
<integer name="columns">3</integer>
<integer name="columns">4</integer>
上記の様に定義したintegerリソースをRecyclerView
やGridView
の列数として指定することで、スマートフォン縦向きでは1列、タブレット縦向きでは2列、小型タブレット横向きでは3列、より大きいタブレットでは4列…というように端末の画面領域に応じてコンテンツの密度を調整できます。
(本来はw640dpで区別するのが良さそうですが、小型タブレットでの利便性を考慮してw600dpで設定しています)
もちろんこのようなレイアウトはすべてのアプリに使えるものではないため、特に縦方向のサイズが重要なレイアウトではport
やland
を使って端末の向き毎に代替リソースを提供したほうが良い場合もあります。
その場合はsw600dp-land
やsw960dp-land
のように短辺と組み合わせて判定することでより厳密になります。
よくある工夫
タブレットにおけるレイアウトのパターンについてはまとめました(古くなっています)。
Androidアプリのタブレット対応レイアウトまとめ