【Android】いまさら聞けないdp入門

  • 515
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

dpとは?

Androidのデザインにおいて、必ず理解しておくべきポイントのひとつがdpについてです。
dp(density-independent pixels)とは密度非依存ピクセルのことで、dipとも呼ばれています。
Androidはこのdpのおかげで多用な端末をサポートできているのです。

dpのない世界 - 端末の解像度ごとに表示サイズが違う
density-test-bad.png

dpのある世界 - 端末の解像度が違っても表示サイズは保たれる
density-test-good.png

Supporting Multiple Screens | Android Developers
More Resource Types | Android Developers

px、dpi、dp

dpを理解する上で欠かせない要素がpx(ピクセル)とdpi(画面密度)です。

px

px(pixel)というのはハードウェアで実装されている解像度そのものです。ピクセルとも言います。
Androidでは端末によって画面解像度が大きく異なる場合があるため、pxで要素を表示すると端末の画面解像度に応じて表示される実サイズがまちまちになってしまいます。
Androidアプリ上でピクセルを直接扱う局面は限られており、ほとんどが画像編集とOpenGL関連です。

pxで要素のサイズを指定した例
density-test-bad.png

dpi

dpi(dots per inch)は画面密度のことで、1インチの中に何ドット含まれているかを表しており、そのままScreen Densityと表現されることもあります。
同じフルHD解像度の端末でもスマートフォンとタブレットではこのdpiが異なっているため、Androidではpxとdpiを考慮したdpという単位が必要だったのです。
ただし、実際のdpiは端末ごとに異なるため、個別にサポートするのはあまり現実的ではありません。
そこで、Androidではdpiをある範囲ごとにランク分けすることにしました。
このランク分けされた画面密度は汎用密度(generalized density)と呼ばれています。

density-ranges.png

Supporting Multiple Screens | Android Developers
Devices and Displays | Android Developers

dp

dp(density-independent pixels)とは密度非依存ピクセルのことで、dipとも呼ばれます。
密度に依存しないピクセルとは、どの画面密度でも同じように表示できるピクセル単位ということです。
dpで指定した値を画面密度に応じて計算することで、実際の端末で表示するpxに変換することができます。
このpxを表示してみるとどの端末でも同じように表示されるため、密度非依存ピクセルと呼んでいるのです。
もちろんここでいう密度とは汎用密度のことなので、実dpiが汎用密度の基準dpiからずれている端末ではわずかに表示サイズに違いが出ます。
汎用密度ではこの問題を考慮し、細かく範囲を設定していますが、「厳密に同じサイズで表示されるわけではない」ということは覚えておく必要があります。

dpで要素のサイズを指定した例
density-test-good.png

汎用密度と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をデザイン領域としています。
metrics_icon.png

このアイコンを汎用密度ごとに用意する場合、以下の様にピクセル数が決まります。

汎用密度 倍率 縦横のサイズ 上下左右の余白 デザイン領域のサイズ
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を使ったりLinearLayoutandroid:layout_weightを使うと自然に対応することができます。
スマートフォンでの横向き表示に対応する場合、横幅が730dpに達する端末もあるので別レイアウトにするかどうかも考慮したほうが良いでしょう。
詳しくはタブレット対応の項を参照してください。

縦方向については480dp-730dpにおさまる場合が多いですが、横幅と違い端末のアスペクト比によってかなり差があります。
ListViewGridViewなどの縦スクロール要素をうまく使って余白が開きすぎないように調整しましょう。
480dpで見切れないレイアウトであっても画面回転に対応する場合はスクロール領域を入れておくべきです。

よくある工夫

リソースを最小短辺サイズ(sw360dpなど)で分割することにより、短辺があるサイズ以上の端末のみに代替リソースを提供することが出来ます。
最小短辺サイズでリソースを分割する際はなるべくdimenを分割するようにしましょう。
layoutを分割してしまうと、後々管理が大変になりがちです。

タブレットとdp

タブレットにおけるdpの注意点やTipsをまとめます。
国内では最近のタブレットの解像度はアスペクト比16:10の1280x800px1920x1200px2560x1600pxが主流ですが、画面サイズが大きいためスマートフォンとは汎用密度が異なることに注意する必要があります。
Android Developersによると、dp解像度では短辺が600-800dp、長辺が960-1280dpの範囲におさまる想定になっています。
metrics_tablet.png

タブレットの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)ごとに分類する方法です。

res/values/values.xml
<integer name="columns">1</integer>
res/values-w600dp/values.xml
<integer name="columns">2</integer>
res/values-w960dp/values.xml
<integer name="columns">3</integer>
res/values-w1280dp/values.xml
<integer name="columns">4</integer>

上記の様に定義したintegerリソースをRecyclerViewGridViewの列数として指定することで、スマートフォン縦向きでは1列、タブレット縦向きでは2列、小型タブレット横向きでは3列、より大きいタブレットでは4列…というように端末の画面領域に応じてコンテンツの密度を調整できます。
(本来はw640dpで区別するのが良さそうですが、小型タブレットでの利便性を考慮してw600dpで設定しています)

もちろんこのようなレイアウトはすべてのアプリに使えるものではないため、特に縦方向のサイズが重要なレイアウトではportlandを使って端末の向き毎に代替リソースを提供したほうが良い場合もあります。
その場合はsw600dp-landsw960dp-landのように短辺と組み合わせて判定することでより厳密になります。

よくある工夫

タブレットにおけるレイアウトのパターンについてはまとめました(古くなっています)。
Androidアプリのタブレット対応レイアウトまとめ