Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

2.01. アプリのレイアウト作成

hidey edited this page Dec 23, 2014 · 4 revisions

GitHub Pagesへ移行しましたmixi-inc.github.ioへお願いします。

wikiの方はしばらくしたら消していきます

この章では、Android アプリ画面のレイアウトの作り方を学びます。

参考:Layouts | Android Developers
参考:Supporting Different Densities | Android Developers
参考:Supporting Multiple Screens | Android Developers

目次

画面を構成する要素

画面を構成する要素となる View には以下のようなものがあります。

TextView、EditText、ImageView、Button、CheckBox、RadioButton といったウィジェット(Widget)と、
LinearLayout、RelativeLayout、FrameLayout といったウィジェットを取りまとめるレイアウト(Layout)です。

これらウィジェットとレイアウトをまとめて、View と呼びます。

View を配置する

View を配置する際に使用する各種パラメータについて説明します。

サイズ

<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"
    tools:context=".MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="hello_world" />

</RelativeLayout>
要素 意味
android:layout_height Viewの高さ
android:layout_width Viewの横幅

android:layout_heightandroid:layout_widthで指定できる値は、数値 dp,sp,pxなどとmatch_parent(fill_parent)とwrap_contentとなります。

match_parentは、親のViewと同じサイズに調整されます。
wrap_contentは、コンテンツを表示するのに十分なサイズに調整されます。上記サンプルの場合、TextViewのサイズは"hello_world"を表示するのに必要なサイズへと調整されます。
fill_parentmatch_parentは同じ機能ですが、API Level 8から非推奨となっています。
API Level 7以下をターゲットとしないのであればmatch_parentを使用しましょう。

パディング、マージン

padding(パディング)、margin(マージン)を使用することでViewの余白を設定することができます。
パディングでViewの内側の余白をマージンで外側の余白を調整することができます。

padding_margin

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#f2f2f2"
        android:padding="12dp"
        android:text="Padding"
        android:textSize="30sp" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:background="#f2f2f2"
        android:text="Margin"
        android:textSize="30sp" />
要素 意味
android:padding 上下左右のパディング
android:paddingTop 上のパディング
android:paddingBottom 下のパディング
android:paddingLeft 左のパディング
android:paddingRight 右のパディング
android:layout_margin 上下左右のマージン
android:layout_marginTop 上のマージン
android:layout_marginBottom 上下のマージン
android:layout_marginLeft 左のマージン
android:layout_marginRight 右のマージン

単位

Androidには様々な画面サイズ、画面密度(解像度)の端末が存在します。
そのためpx(pixel)でサイズ指定をすると端末によって画像が小さくなったり大きくなったりしていしまいます。
Androidではこのような複数解像度の端末に対応するため以下の単位が用意されています。

dp(dip)

dp(dip) は density-independent pixels (密度非依存のピクセル) の略です。

dipは160dpi(dots per inch) の画面を基準とされており、1dipは160dpiの画面では1ピクセルと同等と定義されています。
この関係を式にすると以下のようになり、解像度に対する1dipが何pxに相当するかがわかります。

px = dp * (dpi / 160)

320dpiの画面の場合だと1dipは2pxに自動的に換算され、画面上に反映されることになります。
よって、サイズにdpを使用することで特に意識することなく複数のが解像度端末に対応することができます。

dipとdpは両方使えますがdpの記述の方がspと統一感があるのでわかりやすいです。

sp

spはscale-independent pixels(スケール非依存のピクセル)の略です。

指定したサイズは、解像度とユーザーが設定したフォントサイズにあわせて自動的にスケールされます。

位置

Gravityを使用することでViewを指定した位置に配置することができます。
Gravityは重力をという意味です。Viewに重力をかけることによって、かけた方向へViewが配置されます。
Gravityにはandroid:gravityandroid:layout_gravityが存在し、用途によって使い分けます。

要素 意味
android:gravity 内部の要素の位置を決めます
android:layout_gravity 自分の位置を決めます

android:gravity

内部にTextViewを持ったLinearLayoutandroid:gravity="right"を指定すると以下のようになります。
このことより、TextViewが右に整列されるのがわかります。
gravity_to_parent

<LinearLayout 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:background="@android:color/black"
    android:gravity="right"
    android:orientation="vertical" >

    <TextView
        android:layout_width="180dp"
        android:layout_height="100dp"
        android:background="@android:color/white"
        android:text="Gravity Right1"
        android:textSize="20sp" />

    <TextView
        android:layout_width="180dp"
        android:layout_height="100dp"
        android:background="@android:color/darker_gray"
        android:text="Gravity Right2"
        android:textSize="20sp" />

</LinearLayout>

次は、LinearLayout内部のTextView自体にandroid:gravity="right"を指定すると以下のようになります。
このことより、TextView内の文字が右に整列されます。
gravity_to_textview

<LinearLayout 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:background="@android:color/black"
    android:orientation="vertical" >

    <TextView
        android:layout_width="180dp"
        android:layout_height="100dp"
        android:background="@android:color/white"
        android:gravity="right"
        android:text="Gravity Right1"
        android:textSize="20sp" />

    <TextView
        android:layout_width="180dp"
        android:layout_height="100dp"
        android:background="@android:color/darker_gray"
        android:gravity="right"
        android:text="Gravity Right2"
        android:textSize="20sp" />

</LinearLayout>

android:layout_gravity

内部にTextViewを持ったLinearLayoutandroid:layout_gravity="right"を指定すると以下のようになります。
LinearLayout自体の位置が右に移動しTextViewLinearLayout内での位置は変わっていません。
layout_gravity_to_parent

<LinearLayout 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:background="@android:color/black"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:background="#d1992f"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/white"
            android:text="Gravity Right1"
            android:textSize="20sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/darker_gray"
            android:text="Gravity Right2"
            android:textSize="20sp" />
    </LinearLayout>

</LinearLayout>

次に、LinearLayout内部のTextView自体にandroid:layout_gravity="right"を指定すると以下のようになります。
このことより、TextViewが右に整列されます。
layout_gravity_to_textview

<LinearLayout 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:background="@android:color/black"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:background="#d1992f"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:background="@android:color/white"
            android:text="Gravity Right1"
            android:textSize="20sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:background="@android:color/darker_gray"
            android:text="Gravity Right2"
            android:textSize="20sp" />
    </LinearLayout>

</LinearLayout>

レイアウトを作成する

レイアウトはUIの構造を定義します。
LinearLayout、RelativeLayout、FrameLayout、GridLayout、ListView、ScrollViewなどがあり、用途によって使い分けます。

LinearLayout

Viewを縦横に並べることができます。
android:orientationで並べる方向を決めます。"horizontal" か "vertical"を指定します。
未設定の場合はhorizontalが適用されます。

横に並べる

layout_linear_horizontal

<LinearLayout 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:orientation="horizontal" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text1" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text2" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text3" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text4" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text5" />

</LinearLayout>

android:orientation="horizontal"を指定することによりTextViewが横に並んでいます。
(android:orientation="horizontal"を記述していなくても同様の画面レイアウトになります)

縦に並べる

layout_linear_vertical

<LinearLayout 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:orientation="vertical" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text1" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text2" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text3" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text4" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text5" />

</LinearLayout>

android:orientation="vertical"を指定することによりTextViewが縦に並んでいます。

Layout Weight

LinearLayoutは個々の内部View(子View)に対してandroid:layout_weightを割り当てることができます。
android:layout_weightはViewを配置したときに残っているスペースを埋めることができるとても重要な機能です。

例えば、2つボタンが横並びに配置されているとします。片方のボタンにのみandroid:layout_weight="1"を指定します。
指定していないボタンのandroid:layout_weight0として扱われます。
android:layout_weightは指定された値を元にスペースを割り当てます。この例では割り当てられる比率は1:0となります。
よって、指定されたボタンは残っているスペースを全て使うことになり目一杯横方向に伸びます。

layout_linear_weight

<LinearLayout 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:orientation="horizontal" >

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Button1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2" />

</LinearLayout>

RelativeLayout

相対的にVeiwを配置することができます。
layout_relative

<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"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="A"
        android:textSize="16sp" />

    <Button
        android:id="@+id/b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/a"
        android:layout_toRightOf="@+id/a"
        android:text="B" />

    <Button
        android:id="@+id/c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/b"
        android:layout_below="@+id/b"
        android:text="C" />

    <Button
        android:id="@+id/d"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/c"
        android:layout_alignTop="@+id/b"
        android:layout_toRightOf="@+id/b"
        android:text="D" />

</RelativeLayout>
  1. ボタンAをandroid:layout_centerHorizontal="true"で横方向の中心に、さらにandroid:layout_centerVertical="true"で縦方向の中心に配置しています。またandroid:id="@+id/a"と宣言することでボタンAの識別子を付与しています。
  2. ボタンBはandroid:layout_toRightOf="@+id/a"を指定することでボタンAの右に配置しており、android:layout_alignTop="@+id/a"で上端をボタンAの上端に合わせています。
  3. ボタンCはandroid:layout_below="@+id/b"を指定することでボタンBの下に配置しており、android:layout_alignLeft="@+id/b"で左端をボタンBの左端に合わせるようにしています。
  4. ボタンDはandroid:layout_toRightOf="@+id/b"を指定することでボタンBの右に配置しており、android:layout_alignTop="@+id/b"で上端をボタンBの上端、android:layout_alignBottom="@+id/c"で上端をボタンCの下端に配置するようにしています。
要素 意味
android:layout_above 指定したidのViewの上に配置します
android:layout_alignBaseline 指定したidのViewのベースラインにあわせて配置します
android:layout_alignBottom 指定したidのViewの下端にあわせて配置します
android:layout_alignLeft 指定したidのViewの左端にあわせて配置します
android:layout_alignParentBottom 親となるViewの下端にあわせて配置します
android:layout_alignParentLeft 親となるViewの左端にあわせて配置します
android:layout_alignParentRight 親となるViewの右端にあわせて配置します
android:layout_alignParentTop 親となるViewの上端にあわせて配置します
android:layout_alignRight 指定したidのViewの右端にあわせて配置します
android:layout_alignTop 指定したidのViewの上端にあわせて配置します
android:layout_below 指定したidのViewの下に配置します
android:layout_centerHorizontal 親となるViewの横方向の中央に配置します
android:layout_centerInParent 親となるViewの中央に配置します
android:layout_centerVertical 親となるViewの縦方向の中央に配置します
android:layout_toLeftOf 指定したidのViewの左に配置します
android:layout_toRightOf 指定したidのViewの右に配置します

FrameLayout

FrameLayoutはViewを重ねて配置するのに使用します。
layout_frame

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/FrameLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <!---->
    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="#FF0000" />

    <!---->
    <ImageView
        android:layout_width="190dp"
        android:layout_height="190dp"
        android:background="#00FF00" />

    <!---->
    <ImageView
        android:layout_width="180dp"
        android:layout_height="180dp"
        android:background="#0000FF" />

</FrameLayout>

FrameLayout内の上から順にViewが配置されます。
上記の場合は、赤のImageViewの上に青のImageViewが配置され、その上に緑のImageViewが配置されています。

ScrollView

ScrollViewは画面にレイアウトが収まらない場合、収まらない分をスクロールして表示するための使用します。
layout_scroll

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/ScrollView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="hello_world"
            android:textSize="30dp" />

        ・・・

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="hello_world"
            android:textSize="30dp" />

    </LinearLayout>

</ScrollView>

ScrollViewが持つルートとなるViewは1つでなければなりません。
上記サンプルの場合、複数のTextViewLinearLayoutでまとめ、LinearLayoutをルートとしています。
ScrollViewの直下にTextViewを複数配置するということはできません。

実習・課題

以下の項目に取り組んでください。
レイアウトの参考として、スクリーンショットと同じようなレイアウトになるようにします。
実習・課題の詳細は、各レイアウトファイルの中に記述されています。

  1. (実習) LinearLayoutPractice の 1 と 2 に取り組んでください。
  1. (実習) RelativeLayoutPractice の 1 と 2 に取り組んでください。
  1. (実習) FrameLayoutPractice の 1 と 2 に取り組んでください。
  1. (実習) ScrollViewPractice の 1 に取り組んでください。
  1. (課題) 下記の画像のようなレイアウトが作成されています。このレイアウトを元に、自由にレイアウトを編集してください。
  1. (課題) layout_weightがネストしているので、LinearLayoutRelativeLayoutに置き換かえてネストを解消してください。
  1. (課題) 下記の画像のようなレイアウトを作成してください(課題 6 と同じプロジェクトで実行する)
  1. (課題) 下記の画像のようなレイアウトを作成してください。レイアウトファイル中に、指示と条件、ヒントがあります。
  • スクリーンショット
  • 3 つ並べるボタンの画像の指定は、それぞれ android:src="@android:drawable/ic_menu_call", android:src="@android:drawable/ic_menu_send", android:src="@android:drawable/ic_menu_share" とします

GitHub Pagesへ移行しましたmixi-inc.github.ioへお願いします。

Clone this wiki locally