コンピュータクワガタ

かっぱのかっぱによるコンピュータ関連のサイトです

Androidアプリ入門 No.04 サイズ

ウィジェット共通

サイズ

サイズは以下の種類がある。

種類 説明
sp スクリーン上の相対的な画素サイズに合わせて調整されるピクセル。画面の解像度だけでなくユーザーが設定したフォントサイズにも依存する。
pt デバイスに依存したポイントサイズ。
dpもしくはdip デバイスから独立したポイント。1インチに160ピクセルあると仮定した際に、そこに表示するピクセル数を指定する。つまり、1インチに240ピクセルあるモニタに表示する際に100と指定すると、240/160=1.5となるため、物理モニタには150ピクセル表示される。
px 物理的なピクセルサイズ。

レイアウトにはdip、文字にはspを使うのがデバイス依存しなくてよい。以下の例で確認できる。画面の画素数に対して相対的なサイズになるため、基本的には端末が違っても同様のレイアウトになる可能性が高い。
たとえば、以下のように定義する。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#00f "
    >
<TextView
    android:layout_width="100dip" 
    android:layout_height="wrap_content" 
    android:text="こんにちはメインアクティビティ"
    android:textColor="#000"
    android:background="#80ffffff"
    android:textStyle="italic"
    android:textSize="16sp"
    />
</LinearLayout>

以下の画面で最初の画面が400×240(WQVGA)のサイズで表示した画面、次の画像が800×480(WVGA)のサイズで表示した画面である。画面の比率に応じてサイズが変わっているのがわかる。

ここでもう少し深くdp、spについてみる。まずdpについて確認する。dpは1インチに160ピクセルの画素がある場合のピクセル数を指定することになる。dpに対しての実際のピクセルの計算式は以下のようになる。

表示のピクセル数 = 端末のdensity ÷ 160 × 指定のdp

ここでエミュレータの詳細画面を見てみる。

そうするとhw.lcd.densityという項目があり240という数字になっている。これがこのエミュレータの1インチ当たりのピクセル数となる。
つまり、このエミュレータで120dpを想定すると先の計算式に当てはめると、ピクセル数は180pxとなる。実際にそのように動作しているか、main.xmlを以下のように定義して確かめる。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#ffffff"
    >
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="120dp"
        android:layout_height="50dp"
        android:background="#ff0000">
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="180px"
        android:layout_height="50dp"
        android:background="#00ff00">
    </LinearLayout>
</LinearLayout>

実行結果は以下のようになり、計算が正しいことが確認できる。

次に、spとptの関係を確認する。spとptは直接的には関係しない。以下実例で説明する。まず、MainActivity。

package sample.at;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TextView text1 = (TextView) findViewById(R.id.text1);
        text1.setText("scaled= "
                + getBaseContext().getResources().getDisplayMetrics().scaledDensity);

        TextView text2 = (TextView) findViewById(R.id.text2);
        text2.setTextSize(30.0f);
    }
}

次に、main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@color/blue"
    >
<TextView
	android:id="@+id/text1"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="こんにちはABCabc123"
    android:textColor="#000"
    android:background="#80ffffff"
    android:textSize="30sp"
    />
<TextView
	android:id="@+id/text2"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="こんにちはABCabc123"
    android:textColor="#000"
    android:background="#80ffffff"
    />
<TextView
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="こんにちはABCabc123"
    android:textColor="#000"
    android:background="#80ffffff"
    android:textSize="30sp"
    />
<TextView
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="こんにちはABCabc123"
    android:textColor="#000"
    android:background="#80ffffff"
    android:textSize="20sp"
    />
<TextView
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="こんにちはABCabc123"
    android:textColor="#000"
    android:background="#80ffffff"
    android:textSize="13pt"
    />
</LinearLayout>

実行結果。

次に、MainActivityでscaledDensityを明示して変更する。

package sample.at;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        getBaseContext().getResources().getDisplayMetrics().scaledDensity = 1.0f;
        TextView text1 = (TextView) findViewById(R.id.text1);
        text1.setText("scaled= "
                + getBaseContext().getResources().getDisplayMetrics().scaledDensity);

        TextView text2 = (TextView) findViewById(R.id.text2);
        text2.setTextSize(30.0f);
    }
}

実行結果。text2が小さい文字になっていることが分かる。つまりptやspはscaledDensityには依存しないが、プログラムから明示したsetTextSizeはscaledDensityに依存していることが分かる。

結局spが何者であるかはよく分からない。誰か教えてください。