Mokelab Blog

画面レイアウトの基礎

前回は、アプリにフラグメントを追加するところまでを説明しました。今回は画面レイアウトについて説明します。

View

Androidアプリの画面はViewという部品のツリー構造でできています。Viewの中でも他のViewを子として持てるViewをViewGroupと呼びます。

ConstraintLayout

ツリー構造の起点(ルート)となるViewはConstraintLayoutです。2016年に導入されました。以前はRelativeLayoutをルートにするのが主流でしたが、2019年時点ではConstraintLayoutをルートにして画面レイアウトをするのが主流です。

しかし、Android StudioのフラグメントテンプレートはなぜかFrameLayoutがルートになっています。まずこれをConstraintLayoutに変更します。手でXMLを書き換えるのではなく、Android Studioの機能を使います。

res/layout/fragment_title.xmlを開き、レイアウトエディタを表示します。そして画面の左下にあるComponent Treeで、FrameLayoutを右クリックし、「Convert FrameLayout to ConstraintLayout」を選びます。これでViewツリーのルートがConstraintLayoutに変更されます。

ConstraintLayoutの基本

ConstraintLayoutでは、各Viewが

よう、制約を追加していきます。制約が足りない場合(例えば水平方向でどこに配置すればわからない)はエラーとなり、予期せぬ配置が行われてしまいます。

ViewのID

各ViewにはIDをつけることができます。レイアウトエディタで配置した場合は適当なIDが自動で付与されます。XMLでは、次のように@+id/ID名という値で設定します。

android:id="@+id/login_button"

このIDはJava/KotlinでツリーからViewを取り出すときに使用したり、制約をつけるときのViewの指定に使用したりします。そのため、Viewツリーの中でIDは重複してはいけません。

左端・右端・上端・下端を合わせる

まずは2つのViewの端を合わせる方法です。例えばボタンの上端とテキストの上端を合わせたい場合、レイアウトエディタでボタンを選び、ボタンの上端の●を合わせたいテキストの上端にある●までドラッグします。

XMLで直接編集する場合は、次のようにlayout_constraintTop_toTopOfを使います。

app:layout_constraintTop_toTopOf="@+id/textView"

また、合わせる対象Viewを親のConstraintLayoutにすることもできます。レイアウトエディタの場合は●を画面の端にドラッグします。XMLで直接編集の場合は、対象ViewのIDの代わりにparentを指定します。

app:layout_constraintTop_toTopOf="parent"

例として、TextViewを画面の左上に配置する場合のXML指定です。

<TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_blank_fragment"

        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"/>

テキストの下にボタンを配置する

これもよくあるパターンです。レイアウトエディタの場合、ボタン上端の●をテキスト下端の●にドラッグします。XMLで直接記述する場合は、app:layout_constraintTop_toBottomOf="@+id/textView"のように、layout_constraintTop_toBottomOfを使います。

マージンの指定

マージンを指定することで、View間に隙間をあけることができます。レイアウトエディタではViewを選択し、右側のAttributesのLayoutの所で指定します。XMLで直接記述する場合は、layout_marginTop(上)やlayout_marginBottom(下)などを使います。

例として、左側と上側にそれぞれ8dpのマージンを指定する例です。なお、dp単位がどのようなものかは次回以降で説明します。

<TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_blank_fragment"

        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_marginTop="8dp"
        app:layout_marginLeft="8dp"/>

Viewのサイズ

Viewのサイズはlayout_width(幅)とlayout_height(高さ)で指定します。単位はdp単位を使用します。TextViewやImageViewといった、内部にコンテンツを持つViewの場合、「コンテンツが入るサイズ」というwrap_contentという特殊な値を使用することができます。

水平方向中央に配置する

これまでの例は左端のみ制約を指定していました。そこで右端も同時に制約を指定すると、Viewは両端から引っ張られることになります。この場合、Viewは中央に配置されます。layout_constraintHorizontal_biasを指定すると、左右で引っ張る強さに差をつけ、「中央から少しだけ寄せ」みたいな配置ができます。なお上下の場合はlayout_constraintVertical_biasで指定します。

次の例はTextViewを親Viewの左右中央に配置する例です。LeftとRightの両方が指定されています。

<TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_blank_fragment"

        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

Viewのサイズを水平方向いっぱいにする

Viewに対し、左右の制約をつけると中央に配置されます。この状態で幅を0dpにするとViewのサイズは0dpではなく、制約で左右目一杯に引っ張ったサイズになります。

次の例はメールアドレス入力欄を画面いっぱいにする例です。左端と右端を親Viewに合わせるので、結果として水平方向いっぱいのサイズになります。

<EditText
        android:id="@+id/edit_email"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/hello_blank_fragment"

        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

まとめ

ConstraintLayoutを使ったレイアウト方法を説明しました。画面レイアウトはアプリ開発で何度も行うことになるので、自由自在にレイアウトできるようになりましょう。

本サイトではサービス向上のため、Google Analyticsを導入しています。分析にはCookieを利用しています。