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

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

 




ピクセル密度

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

例えばピクセルサイズの画像の貼り付けをしたい時に問題があります。

  • 端末のピクセルの画面サイズに合わせて画像を拡大縮小させないといけない
  • 端末によるピクセル密度が異なることもあるので、同じピクセルサイズの画面でも物理サイズが違う場合、見え方が違う

そのために dp、sp という画面サイズ、インチ数を包括し統一的に扱うことを目的とした抽象的な単位をAndroidでは提供されているわけです。
 
例えば、ボタンの横幅を360dpに設定すると多くのスマホで「スクリーン横幅一杯のサイズになる」というような仕組みがあれば便利、というわけで、Googleさんが作ったのが dp とsp(フォント用)です。(実際はそれほど簡単とはいかないのではありますが)
 

 

解像度単位 dp, sp

 
画像やテキストサイズはデジタルの世界ではピクセルという点が基本で、点が集まって画像になったり文字になったりします。

ピクセル自体には物理的大きさはないのですが、PC画面や印刷物になるといきなり物理的な関連が出てきます。dipとdpiが似ているのでややこしいのですが…

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

Google Ref:Supporting Multiple Screens
 
dpiを取得するコード


 
尚こちらの方法はAPI30から非推奨となりました


dpを取得する


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

Button サイズで dp, pix の関係を見てみます。

  1. 1dp = 2.75 pix
  2. 150dp x 150dp サイズのボタン
  3. 200dp x 100dp サイズのボタン
  4. 200dp x 100dpと同じサイズを 550pix x 275pix で作成

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

コードはこのようになります
MainActivity.java


activity_main.xml


 

画面サイズ、dpi、dpの関係

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

密度修飾子 密度 dpi scale px : dp 画面サイズ
ldpi 低密度 120 0.75 1[px] = 0.75[dp] 240 x 320[px]
mdpi 中密度 160 1.0 1[px] = 1.0[dp] 360 x 640[px]
hdpi 高密度 240 1.5 1[px] = 1.5[dp] 540 x 960[px]
xhdpi 超高密度 320 2.0 1[px] = 2.0[dp] 720 x 1280[px]
xxhdpi 超超高密度 480 3.0 1[px] = 3.0[dp] 1080 x 1920[px]
xxxhdpi 超超超高密度 640 4.0 1[px] = 4.0[dp] 1440 x 2560[px]

 
Screenサイズはhdpiでも、4インチ480×800、3.7インチ480×854などあります。スクリーン解像度のピクセル数と dpi が比例関係にはなく、画面の物理的大きさ(インチ数)も考慮されているということです。
 
1x1.trans - [Android] dp, px, dpi, sp アプリ画面の解像度単位を包括・統一的に扱う


Ref: さまざまな画面サイズをサポートするための推奨幅ブレークポイント
 

 
ちなみに こちらの方法で Pixel や Nexus のスクリーンサイズを取得するとこのようになります。
 

as413k m42 00 100x100 - [Android] dp, px, dpi, sp アプリ画面の解像度単位を包括・統一的に扱う
アプリの画面サイズを取得したい場合があります。タブレットとスマホで表示を変えたい。あるいはテキストの位置を正確に表示したいなど 実際に...

 
以前は360dp x 640dpを基本として考えて例外を調整するなどで対応していたりしましたが、410dp x 730dp 以上が出てきたので対応が必要になりましたね

 

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

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


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


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

ただ、ユーザーが老眼だったりすると文字が小さくて見えないという不満がでるでしょうね…その辺も考慮する必要もあります。

 
References:
画面互換性の概要 | Android デベロッパー
各種のピクセル密度をサポートする | Android デベロッパー
配信ダッシュボード | Android デベロッパー
Pixel density | MATERIAL DESIGN
各種の画面サイズのサポート | Android デベロッパー

シェアする

  • このエントリーをはてなブックマークに追加

フォローする