[Android] dp, px, dpi, sp アプリ画面の解像度単位を包括・統一的に扱う

Android ではスクリーン上の長さを、抽象的な単位「dp」「sp」で表すそうです。実際アンドロイドの画面サイズ解像度はメーカーによってまちまちですから、アプリを開発する側からすると何か便利な方法はないかと考えてしまいます。

 

sponsored link

解像度単位 dp, sp

 
Androidは様々なスクリーンサイズ(インチ)で、更に異なる画素数(ピクセル)のものが販売されていて、その1つ1つに合わせたレイアウト・デザインを作り込むのは大変です。

なので、解像度単位 dp, sp は画面サイズ、インチ数を包括し統一的に扱うことを目的とした抽象的な単位です。
 
例えば、ボタンの横幅を360dpに設定すると多くのスマホで「スクリーン横幅一杯のサイズになる」というような仕組みがあれば便利、というわけで、Googleさんが作ったのが dp とsp(フォント用)
 
Google Ref : Supporting Multiple Screens
 

 dp   dip, density-independent pixel  抽象的な単位、mdpi (160 dpi) を基準とし、
mdpi のとき 1dp = 1px となる
 sp  scale-independent pixel ユーザーが設定したフォントサイズに影響される
 px  pixel  ピクセル、物理的な表示用セル
 dp  dots per inch 1インチ幅のドット数、値が大きいほど1ドットの
物理的な大きさが小さくなり、よりきめ細かくなる。

 
DPIを取得するコード
 

 
DIPを取得する

例えば
150dp => (int)(150 * scale)
となります

画面サイズ、dpi、dpの関係を表にすると
 

         スクリーンサイズ例    
 ldpi  120[dpi]   0.75   1[px] = 0.75[dp]   240 x 320[px]  320 x 427[dp] 
 mdpi  160[dpi]  1.0  1[px] = 1.0 [dp]  360 x 640[px]  360 x 640[dp]
 hdpi  240[dpi]  1.5  1[px] = 1.5 [dp]  540 x 960[px]  360 x 640[dp]
 xhdpi  320[dpi]  2.0  1[px] = 2.0 [dp]  720 x 1280[px]  360 x 640[dp]
 xxhdpi   480[dpi]  3.0  1[px] = 3.0 [dp]  1080×1920[px]  360 x 640[dp]

 
Googleの2013/12のデータではhdpiが一番多いようです
 
Screen Sizes and Densities

 
dpi
 
Screenサイズはhdpiでも、4インチ480×800、3.7インチ480×854などあります。スクリーン解像度のピクセル数とDPIが比例関係にはなく、画面の物理的大きさ(インチ数)も考慮されているということです。

Googleの解説を見てもそれぞれのサイズ定義の境界あたりはグレーな感じで、システム任せとも読み取れますが…
 
この他に tvdpi, xxxhdpi などもあり、tvdpi はこのサイズのスマホはあまりないのですが、Nexus7(2012)がtvdpiです。
ちなみにNexus7(2013)では 1920x1200px で323ppiにスペックが上がってます。
xxxhdpi は4K television screensを想定しているようです、スマホで4K!?
 

SPサイズはユーザー設定で変わる

 
SPのサイズはユーザーが設定でフォントサイズを設定でき、それによってスケーリングされます。
スマホの [設定] -> [ディスプレイ] -> [フォントサイズ]
 
このため、spで設定した文字は、ユーザーのフォントサイズによって変化する

 
レイアウトはspサイズになりますが、ユーザーがフォントサイズを変えると画面上で大きくなったり小さくなったりします。
 
それでは、狙った画面レイアウトができません
それを阻止するためには
 

 
のように COMPLEX_UNIT_DIP を入れ
TypedValue を設定する必要があります。
 
あるいは画像として文字を入れてしまうのも手す、dpとしての縛りがありますが