メトリックとグリッド
Androidの寸法単位
Androidデバイスはさまざまなメーカーから、さまざまな画面サイズ、画面密度の機種が販売されています。
各々に対応するために、Androidでは全部で6種類の寸法単位が存在します。
寸法単位は大きく分類して、相対的な単位と絶対的な単位が存在します。
相対的な単位はどのような機種上でアプリケーションを実行しても、ほとんど同じ画面レイアウトとなります。絶対的な単位は、常に同じピクセル数やミリメートルによって表示されるため、端末によってレイアウトが異なります。
以下にAndroidの寸法単位の一覧を示します。
単位 | 概要 | |
---|---|---|
相対的な単位 | dp(dip) | 密度非依存ピクセル。画面のドット密度を基準とした抽象的な単位。160dpiの画面において、1dp=1pxとなり、実際の画面のドット密度により、相対的に変化する。dpとdpiは名前が似ているが、別物なので要注意。 |
sp | スケール非依存ピクセル。dpに似ているが、ユーザーのフォントサイズの設定により伸縮される。画面密度とフォントサイズの両方加味されるため、フォントサイズの指定では推奨される単位となる。 | |
絶対的な単位 | px | 画面の実際のピクセルに対応する。(非推奨)デバイスによりインチ毎のピクセルが異なっているため |
in | インチ。物理的なサイズ。(非推奨) | |
mm | ミリメートル。物理的なサイズ。(非推奨) | |
pt | ポイント(1/72インチ)。物理的なサイズ。(非推奨) |
※解像度
画面の物理ピクセルの総数。
※画面密度
画面の物理的な領域内のピクセルの数で、通常はdpi (1インチあたりのドット数)と呼ばれている。
ピクセルとdpの違い
ここでdpについて少しだけ捕捉します。
Eclipseのパッケージエクスプローラのresフォルダの中には「hdpi」や「ldpi」というフォルダなどが存在します。
各フォルダには、各解像度に適応するファイルが格納されます。
Androidでは解像度が5つ存在しており、詳細を以下に示します。
画面密度 | 倍率 | サイズ | 概要 |
---|---|---|---|
ldpi | mdpi×0.75倍 | ~120dpi | low密度画面用のリソース |
mdpi | mdpi×1.0倍 | ~160dpi(1dpで1px) | medium密度画面用のリソース |
hdpi | mdpi×1.5倍 | ~240dpi | high密度画面用のリソース |
xhdpi | mdpi×2.0倍 | ~320dpi | extra high密度画面用のリソース |
xxhdpi | mdpi×3.0倍 | ~480dpi | extra extra high密度画面用のリソース |
ピクセルとdpの違いに関して、もう少し具体的に確認してみましょう。
まず、160dpi (1インチ当たり160ドット)の画面と320dpi (1インチ当たり320ドット)の画面があった場合、ピクセルで幅等を決めていると、下図のように1ピクセルあたりの物理的な大きさが異なる、という状態になります。
160dpiの1ピクセル 320dpiの1ピクセル
Androidではこのような事態を防ぐためにdpを使用します。
上記の例では、1ピクセルの物理的なサイズが異なってしまいましたが、dpを用いることによって、以下のように画面密度(dpi)の異なる画面でも、物理的なサイズをほぼ同じにすることができます。
160dpiの1dp 320dpiの1dp
実際にアプリケーションを作成する際は、画面サイズを480px×800pxを想定することが一般的です。
そして作成が完了したら、さらに画面サイズが大きい端末で検証します。
幅、高さ、パディング、マージンはdp(dip)で指定し、文字だけ端末のフォント設定に合わせるべくspで指定します。
文字の設定は、一般的に12sp以上20sp以下の値にします。
Android Developerのデザインパターンを参考にするとわかりやすいです。
Android Developer | Metrics and Grids
テキストサイズに使用するsp
テキストサイズにspを用いた場合の変化を確認します。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="15dp" > <Button android:id="@+id/button1" android:layout_width="120dp" android:layout_height="48dp" android:text="SAK" android:textSize="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="48dp" android:layout_alignTop="@+id/button1" android:layout_toRightOf="@+id/button1" android:gravity="center_vertical" android:text="System Architure Knowlege" android:textSize="20sp" /> </RelativeLayout>
上記サンプルコードでは、12行目ではButtonのテキストサイズを「20dp」としています。
それに対して21行目ではTextViewのテキストサイズを「20sp」としています。
以下の図は、エミュレータのフォントサイズを「小」(左図)から「極大」(右図)に変化させた図です。
Buttonのフォントは変化していませんが、TextViewのフォントが変化していることが確認できます。
ところで画面レイアウトファイルで「android:textsize」属性を指定しない場合(デフォルト)では、フォントサイズの単位にspを使用しています。
言い換えれば、端末のフォントサイズの設定に依存するようになっています。
ユーザービリティ
さて、ユーザーインタフェースのデザインを検討する上で、最も意識する必要があるのはユーザービリティ(使い易さ)でしょう。
ユーザーが触れることのできるコンポーネントは、一般的には48dpに沿ってレイアウトされています。
なぜ48dpなのでしょうか?
48dpは物理的なサイズに変換すると、多少の誤差はありますがおよそ9mmです。
このサイズはユーザーが確実に操作できる推奨サイズ(7-10mm)の範囲内だからです。
48dpで作成すると7mm以下になることはありませんので、そこまでユーザービリティを意識する必要がなくなります。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="15dp" > <Button android:id="@+id/button1" android:layout_width="120dp" android:layout_height="48dp" android:text="SAK" /> <TextView android:layout_width="wrap_content" android:layout_height="48dp" android:layout_alignTop="@+id/button1" android:layout_toRightOf="@+id/button1" android:gravity="center_vertical" android:text="System Architure Knowlege" /> </RelativeLayout>
上記のコードではButtonの高さも、TextViewの高さも、どちらも48dpとしています。
以下の図は解像度が480×800と、320×480の2台(どちらの画面密度もmdpi)のエミュレータを用意し、上記のサンプルアプリケーションを実行した場合の実行結果です。画面は異なりますが、Buttonのサイズがあまり変化していないことがわかると思います。
※ただし横幅は端末に依存するため、横幅が短いと改行されます。