はじめに

今回の勉強会では、画面部品の配置まで行っていきます。

今回の勉強会が一通り実践できるようになると、下記のようなことができるようになります!

  • 入力フォームやボタンなどの、画面部品を作れるようになる!
  • ConstraintLayoutを用いて、直感的な操作でレイアウト(アプリの見た目)を調整することができる!

今回のキーポイント

  • 画面部品である、ビューの理解
  • デザインエディタの操作を学ぶ
  • ConstraintLayoutによるレイアウト調整

画面部品の配置方法を学び、このような見た目のアプリを作ってみましょう!

前回の内容はこちら

サンプリプロジェクトを作成しよう!

今回のサンプルアプリを作るために、新たにプロジェクトを作成します。
前回の資料を参考にしながら進めましょう。

  • Project Template: Empty Activity
  • Name: DisplayProfile
  • Language: Kotlin
  • minimum SDK: API 21 Android 5.0 (Lollipop)

上記情報を設定し、プロジェクトを作成します。
Package nameやSave locationは以下のように、自動的に入力されます。アプリの機能に影響しない箇所なので、今回はこの内容のまま進めます。変更したい方は適宜修正してください。

  • Package name: com.example.displayprofile
  • Save location: /Users/<アカウント名>/AndroidStudioProjects/DisplayProfile

今回のゴール:xmlファイルの完成

今回は先に、ゴールをお見せします。

今回のゴールはアプリの見た目を完成させることです。そして、アプリの見た目は、XMLファイル(〇〇.xml というファイル)が担っています。
つまり、アプリの見た目を決定しているXMLファイルを作ることが今回のゴールです。

以下のファイルが、今回の完成形です。この時点では、これら2つのファイルにはほぼ何も書かれていないかと思います。
今回の勉強会を通して、これらのファイルを一緒に作り上げていきましょう!

これ以降の作業でエラーが発生したり予期せぬ状態になった場合は、こちらのファイルと比較していただければと思います。

strings.xml

<resources>
  <string name="app_name">プロフィール表示アプリ</string>
  <string name="tv_title">プロフィールを入力してください</string>
  <string name="tv_name">名前</string>
  <string name="tv_from">出身</string>
  <string name="tv_language">学習中の言語</string>
  <string name="bt_display">表示</string>
  <string name="bt_clear">クリア</string>
</resources>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

  <TextView
      android:id="@+id/tvTitle"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginTop="8dp"
      android:text="@string/tv_title"
      android:textAlignment="center"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent" />

  <TextView
      android:id="@+id/tvName"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginEnd="8dp"
      android:text="@string/tv_name"
      android:textAlignment="center"
      app:layout_constraintBaseline_toBaselineOf="@+id/etName"
      app:layout_constraintEnd_toStartOf="@+id/etName"
      app:layout_constraintStart_toStartOf="parent" />

  <EditText
      android:id="@+id/etName"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:layout_marginEnd="8dp"
      android:ems="10"
      android:inputType="textPersonName"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="@+id/guideline"
      app:layout_constraintTop_toBottomOf="@+id/tvTitle" />

  <TextView
      android:id="@+id/tvFrom"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginEnd="8dp"
      android:text="@string/tv_from"
      android:textAlignment="center"
      app:layout_constraintBaseline_toBaselineOf="@+id/etFrom"
      app:layout_constraintEnd_toStartOf="@+id/etFrom"
      app:layout_constraintStart_toStartOf="parent" />

  <EditText
      android:id="@+id/etFrom"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:layout_marginEnd="8dp"
      android:ems="10"
      android:inputType="textPersonName"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintHorizontal_bias="0.0"
      app:layout_constraintStart_toStartOf="@+id/guideline"
      app:layout_constraintTop_toBottomOf="@+id/etName" />

  <TextView
      android:id="@+id/tvLanguage"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginEnd="8dp"
      android:text="@string/tv_language"
      android:textAlignment="center"
      app:layout_constraintBaseline_toBaselineOf="@+id/etLanguage"
      app:layout_constraintEnd_toStartOf="@+id/etLanguage"
      app:layout_constraintStart_toStartOf="parent" />

  <EditText
      android:id="@+id/etLanguage"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:layout_marginEnd="8dp"
      android:ems="10"
      android:inputType="textPersonName"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintStart_toStartOf="@+id/guideline"
      app:layout_constraintTop_toBottomOf="@+id/etFrom" />

  <Button
      android:id="@+id/btDisplay"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginBottom="8dp"
      android:text="@string/bt_display"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toStartOf="@+id/btClear"
      app:layout_constraintHorizontal_chainStyle="spread"
      app:layout_constraintStart_toStartOf="parent" />

  <Button
      android:id="@+id/btClear"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:layout_marginBottom="8dp"
      android:text="@string/bt_clear"
      app:layout_constraintBottom_toBottomOf="parent"
      app:layout_constraintEnd_toEndOf="parent"
      app:layout_constraintHorizontal_bias="0.5"
      app:layout_constraintStart_toEndOf="@+id/btDisplay" />

  <androidx.constraintlayout.widget.Guideline
      android:id="@+id/guideline"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="vertical"
      app:layout_constraintGuide_percent="0.25" />

</androidx.constraintlayout.widget.ConstraintLayout>

ファイルはどこにある?

今回は、XMLファイルを新たに作成するのではなく、既存のXMLファイルを編集する形で進めます。
最初にすることは、編集対象の

  • string.xml
  • activity_main.xml

を探して表示させることです。

Android Studio の左側、Projectツールウィンドウ上部のドロップダウンリストから
Android
を選択します。

これにより、Androidアプリ開発に必要なファイルのみが表示されるようになります。
ここから、appフォルダを開きます。
この中のresフォルダに、今回編集したいファイルが置かれています。

resフォルダは、アプリの見た目を決めるためのファイルが格納されています。resフォルダ内のサブディレクトリは以下のとおりです。

  • drawable: 画像
  • layout: XMLファイル
  • mipmap: アイコン画像
  • values: アプリで扱う文字列、画面スタイル、色 を決めるXMLファイルなど

今回扱うファイルは、

  • string.xml: valuesフォルダ
  • activity_main.xml: layoutフォルダ

に格納されています。これらをダブルクリックして開きましょう。

ビュー(画面部品)とは

アプリの見た目を構成する画面部品はビューと呼ばれています。
今回は、ビューをXML内で定義していくことになります。

代表的なビュー

Androidアプリ開発でよく使われる代表的なビューを紹介します。
本勉強会では、このうちの TextView, EditText, Bottunの3種類を使用します。



TextView: 文字列を表示する
EditText

EditText: 文字列を入力する
Button

Button: ボタン
RadioButton

RadioButton: ラジオボタン
Checkbox

CheckBox: チェックボックス
Seekbar

SeekBar: スライダー

デザインエディタを使って、ビューを配置しよう!

それではいよいよ、XMLファイルを編集してビューを配置します!
手始めに、「プロフィールを入力してください」という文字列を表示させてみましょう。

strings.xmlの記入

ビューを配置する前に、ビューに表示させる文字列をstrings.xmlに記入します。
以下のように、「プロフィールを入力してください」という文字列を定義します。
今のうちに、アプリ名も変更しておきましょう。 <string name='app_name'> がある行、DisplayProfileを プロフィール表示アプリ に変更します。

strings.xml

<resources>
  <string name="app_name">プロフィール表示アプリ</string>
  <string name="tv_title">プロフィールを入力してください</string>
</resources>

ビューを置いて、とりあえずアプリ実行

次に、ビューを配置するためのファイル、activity_main.xmlを開きます。

activity_main.xmlはlayoutフォルダに格納されている、レイアウトファイルの一種です。レイアウトファイルを表示させると、専用のエディタに自動的に切り替わります。
このエディタはレイアウトエディタと呼ばれています。

このレイアウトエディタにはモード切替機能があります。
エディタの右上に3種類のアイコンがあります。それを押すことでモードの切り替えができます。

コードをそのまま記入するCode, 実際のアプリの見た目に近い状態で編集できるDesign、両方を表示するSplit の3種類があります。
今回はこのうちのDesignモードを使用します。

Codeモード
Designモード

Designモードには、2種類の画面が表示されています。左の白い画面をデザインビュー、右の青い画面はブループリントビューと呼ばれています。
デザインビューでは実際のアプリとほぼ同じ見た目が表示され、ブループリントビューでは部品の枠線のみが表示されます。
作業内容によって見る画面を適宜変えてください。どちらの画面でも同じ作業が可能です。

エディタ左側にビューを選択できるウィンドウがあります。

その中からTextViewを選び、そのままドラッグしてエディタ真ん中の白画面まで移動させます。

すると、下図のように TextView と書かれた文字列が配置されます。
これ以降、配置されたTextViewをラベルと呼びます。ラベル = TextViewと置き換えて考えていただければと思います。

配置されたラベルをクリックすると、エディタ右側のAttributesウィンドウが以下のような表示になります。


この画面でラベルの詳細を編集します。idとtextを、

  • id: tvTitle
  • text: @string/tv_title

と変更しましょう。
idは、アプリ内の各ビューを識別するための名前です。どのような機能をもったビューなのかが理解しやすくなるような名前にしましょう。ただし、他のビューと名前が被ってはいけません。
TextViewでは、textで定義した文字列がそのまま表示されます。@string/... と入力することで、strings.xmlで定義した文字列をここで使えるようになります。

ここまでできたら、アプリを起動してみましょう。
※起動のしかたは前回の勉強会資料を御覧ください。

「プロフィールを入力してください」の表示が左上に表示されています。
エディタでラベルを真ん中に配置していたとしても、アプリ上ではこのような表示になってしまいます。

これは、ビューの位置を適切に定義していないからです。
思い通りの位置で表示されるために、Designモードでレイアウトを整える作業を行います。

レイアウトを整えよう!

ビューの制約

AndroidStudioに戻り、引き続きDesignモードでactivity_main.xmlを編集します。

「プロフィールを入力してください」が表示されているラベルをクリックすると、各辺に白い丸が現れます。上の丸をクリックしながら上へドラッグすると、色が変わって矢印が表示されます。

このまま画面上端までドラッグさせると、ビューが自動的に上端に移動します。
同様にして、ビューの下の丸を画面下端までドラッグさせます。すると、ビューがちょうど中央に配置されます。ビューが上端と下端から同じ力で引っ張られている、と考えるとイメージしやすいかと思います。

このようにして、直感的な操作でビューの位置を決めることができます。
このとき、ビューの上端と画面上端、ビューの下端と画面下端に相対的な位置関係が定義されています。この関係のことを制約といいます。

この画像には alt 属性が指定されておらず、ファイル名は image-43.png です

制約の解除

制約の解除も直感的に行えます。ビューを選択してから制約を表す記号をクリックすると、選んだ制約がハイライトされます。この状態でdeleteキーを押すと制約が解除されます。
下端の制約を解除することで、ビューが上端に移動することが確認できます。

この画像には alt 属性が指定されておらず、ファイル名は image-42.png です
この画像には alt 属性が指定されておらず、ファイル名は image-38.png です

テキストの中央寄せ

配置したラベルをブループリントビューで確認すると、文字が枠内で左寄せ担っていることがわかります。
これを中央寄せにしましょう。


ラベルを選択した後、エディタ画面右側のAttributeウィンドウから textAlignmentを選択します。
Attributeウィンドウを下にスクロールして探す、またはウィンドウ右上の虫眼鏡アイコンを選択し検索してください。
textAlignment をCenterにすることで、テキストが中央寄せされます。

入力フォームの定義

続いて、入力フォームを定義します。
ラベル(TextView)と同様、エディタの左側からビューをドラッグしてくるのですが、今回はPlainTextを選びましょう。下図のように虫眼鏡アイコンを選択することで、ビューの検索が可能です。

補足:
PlainTextという名前のビューをドラッグしてきましたが、実はPlainTextという名前のビューはありません。EditTextというビューのうち文字列を入力する機能だけを持つものをDesignモード上でPlainTextと名付けています。
Codeモードで確認すると、PlainTextに対応するタグが<EditText>であることがわかります。

入力フォームを画面にドラッグしたら、先ほどと同じく制約を定義します。
入力フォームの上の丸をラベルの下の丸までドラッグさせます。すると、2つのビューが上下にぴったりくっついた状態になります。

上下の制約ができたので、左右の制約を付けましょう。左の丸をドラッグして画面左端までもっていきます。この操作を2つのビュー両方で行うと、以下の状態になります。

以上で、ビューの位置が確定しました。
ビューの制約は縦横にそれぞれ1つずつ指定すれば十分です。上図の場合、

  • ラベル: 上端と画面上端、左端と画面左端
  • 入力フォーム: 上端とラベル下端、左端と画面左端

で制約が定義されています。配置場所を相対的に決めることができるこのようなレイアウトをConstraintLayoutといいます。
ConstraintLayoutのおかげで、簡単で融通のきくレイアウトを実装することができるようになりました。

ビュー配置の微調整

ビューの位置が決まったものの、すべてのビューが左上端に偏っています。この状態だと見た目が良くないので、配置を調整します。

まずは、ラベルと画面端の間に隙間を作りましょう。
ラベルをクリックすることで、以下の図の状態になります。これから使うのは、エディタ右下部のConstraint Widgetです。

上と左にあるプルダウンを選択し、0 → 8 に変更しましょう。すると、ラベルの上部と左部に隙間ができました。このプルダウンは、対応する制約に隙間を定義するためのものです。

次に、入力フォームを左右いっぱいに伸ばしてみましょう。入力フォームの右端と画面右端にも制約を定義し、左右の中心に入力フォームが置かれるようにします。
このままでは、左右いっぱいに入力フォームが広がりません。この制約を調整する際も、ConstraintWidgetを使います。

左右に制約を定義した直後は、以下の図のようになっています。Constraint Widgetの左右の制約を表す記号、
>>  <<
のアイコンを2回クリックしてみましょう。

すると、以下の図のようになります。これは、制約の範囲内で画面いっぱいに広げる、match constraint という状態です。
この状態でも、隣り合う要素と隙間をあけることができます。先程と同様、上と左右の隙間を 0 → 8に変更しましょう。

補足:デフォルトマージン
先程のように決まった隙間を開ける場合、ことあるごとに 0 → 8 の変更をするのは面倒ですよね。
制約を定義した際に、自動的に隙間をあけるデフォルトマージン設定があります。
常に一定の隙間をあけたいばあいは、下図を参考にして設定してください。

この画像には alt 属性が指定されておらず、ファイル名は スクリーンショット-2020-05-17-4.34.53.png です

これ以降ビューに隙間を空ける場合、特に指定をしない限り8dp空けるものとします。

残りのラベル, 入力フォームの定義

ここまで学んだことを思い出し、ボタン以外の残りのビューを定義しましょう。
入力フォームのid, textの説明は省略しておりましたが、ラベルと同じ操作で修正することができます。


strings.xmlにて、以下のように文字列を定義してください。

<resources>
  <string name="app_name">プロフィール表示アプリ</string>
  <string name="tv_title">プロフィールを入力してください</string>
  <string name="tv_name">名前</string>
  <string name="tv_from">出身</string>
  <string name="tv_language">学習中の言語</string>
</resources>

他のビューのid, textは以下を使ってください。
すでに設定したtvTitleの情報も載せておきますので、参考にしてください。

idtext役割
tvTitle@string/tv_title「プロフィールを入力してください」
を表示 ※テキスト中央寄せ
tvName@string/tv_name「名前」を表示 ※テキスト中央寄せ
tvFrom@string/tv_from「出身」を表示 ※テキスト中央寄せ
tvLanguage@string/tv_language「学習中の言語」を表示 ※テキスト中央寄せ
etName(空欄)名前を入力するフォーム
etFrom(空欄)出身を入力するフォーム
etLanguage(空欄)学習中の言語を入力するフォーム

下図のようなビュー配置になればOKです。すべての隙間は8dpだけ空けています。

ビュー配置のさらなるカスタマイズ

ボタンの定義

ボタンも、ラベルと同様に設定することができます。
エディタ左側からButtonを選択し、画面にドラッグしましょう。

2種類のボタンを画面下部に設定します。strings.xmlへの記載事項、id, textの情報は以下のとおりです。

stirngs.xml

<resources><string name="bt_display">表示</string>
  <string name="bt_clear">クリア</string>
</resources>
idtext役割
btDisplay@string/bt_display「表示」ボタン
btClear@string/bt_clear「クリア」ボタン

細かい位置調整は後ほど行いますので、とりあえず下図のようにボタンを設置してください。
ボタン下部と画面下部に制約を定義し、2ボタンの間に制約を定義します。隙間は8dp空けます。デフォルトマージンを設定していれば、ボタンの白い丸をドラッグするだけで設置できます。

制約の変更

ラベルと入力フォームを横並びにしてみましょう。「名前」のラベルと名前を入力するフォームに注目して、横並びにするやり方をご説明します。

現状で既に制約が完成している状態なので、制約を移し替える操作を行います。
入力フォームをクリックすると、現在定義されている制約が表示されます。
制約が定義されている辺には青い丸、定義されていない辺には白い丸が表示されていることがわかります。

ここから、入力フォーム左辺の丸をクリックし右へドラッグすると、矢印が現れます。
ドラッグしたまま、その矢印を「名前」ラベルの右辺(白い丸)へもっていきましょう。

すると、下図のような配置になります。上下のズレはあるものの、「名前」ラベルと名前入力フォームが左右に繋がるような制約が完成しました。

次に、上下のズレを解消します。現状、入力フォームの上に「名前」ラベルが置かれるような制約になっていますが、これらが横並びになったとき、入力フォームの上には「プロフィールを入力してください」ラベルがあるべきです。

したがって、入力フォーム上辺の青丸をドラッグし矢印を表示させたら、「プロフィールを入力してください」ラベルの下辺に矢印をもっていきます。
先程と同様にして、制約を移し替えましょう。

ここまでの操作で、下図のような位置関係になりました。隙間が詰まってる場合は、Constraint Widgetを用いて手動で隙間を空けてください。

この一連の操作を残り2つの入力フォームで行うことで、以下の見た目が完成します。

ベースライン

対応するラベルと入力フォームが上揃えで並んでいますが、あまりキレイな見た目ではないですね。ベースラインという機能を用いて、文字の位置をを揃えましょう。

ラベルを右クリックするとメニューが現れます。ここから、Show Baselineを選択してください。すると、ラベルの下側に白い太い線が表示されます。これがベースラインです。
ラベルの選択を外すとベースラインが見えなくなるので、見えなくなったら再度ベースラインを表示させてください

この画像には alt 属性が指定されておらず、ファイル名は image-67.png です

ベースラインをクリックしてドラッグすると、辺の白丸をドラッグしたときと同様の矢印が表示されます。
それと同時に、他のビューのベースラインも自動的に表示されます。
このうち、横並びになっている入力フォームのベースラインへ矢印をもっていきます。

この操作でベースラインが揃い、ラベル文字とフォームに入力する文字の位置が揃うようになりました。

この画像には alt 属性が指定されておらず、ファイル名は スクリーンショット-2020-05-17-12.35.26.png です

出身ラベル、学習の言語ラベルにも同様の操作を行い、以下のようにベースラインを合わせましょう。
ラベルと入力フォームはあと少しで完成です!

ガイドライン

この状態でも十分キレイな見た目になりました。しかし、さらに欲を言うと、入力フォームの左端の位置を揃えたいですね。
ここでは、位置を揃えるための目安となる補助線、ガイドラインを使ってみましょう。

エディタ上部、のガイドラインアイコンをクリックし、Add Vertical Guidelineを選択します。
アイコンの場所は下図をご参照ください。

ガイドラインがエディタ上に点線で表示されます。
今回は、画面左端から画面幅の1/4だけ右に離れたところにガイドラインを設置してみましょう。

ビューと同様、ガイドラインを選択してドラッグすることで大まかな位置を決めることができます。
ドラッグすることで位置が大まかに決まります。
しかし、現状の設定だと、『画面左端から〇〇dpだけ離れた位置』という設定でガイドラインが配置されてしまいます。

今回は、いかなる画面幅のデバイスであっても、画面1/4の位置にガイドラインを置きたいです。
この設定ではそれが実現できないので、ガイドラインの配置設定を変更します。

ガイドライン上部、黒い三角アイコンが表示されていますが、これをクリックします。
すると、ガイドライン配置設定が切り替わります。何回かクリックし、『%』と表示させましょう。

この状態は、画面左端を0%(または0), 右端を100%(または1)としたときの位置を定義するモードです。この状態なら、画面1/4の位置にガイドラインを置くことができます。

ガイドラインを選択していれば、エディタ右部、Attributesウィンドウにガイドラインの詳細情報が表示されているはずです。
このウィンドウ内、layout_constraintGuide_percent (小数が入力されている箇所) を0.25に変更します。

これでガイドラインの位置が正しく決まりました。このガイドラインを基準にして、入力フォームとラベルの位置を以下の図のように調整してみましょう。

ヒント:
①入力フォームとガイドラインの隙間は0dpです。
②名前、出身、学習の言語ラベルは、画面左端とガイドラインの両方から引っ張られている状態です。

これで、ラベルと入力フォームが完成しました!!

チェイン

残るビューは2つのボタンです。画面下部に仮置きしていましたが、これらをキレイに並べましょう。
今回はチェイン機能を用いて、複数のビューを均等な間隔で並べます。

まず、ボタン2つを選択します。ドラッグして範囲選択、またはCommandキーを押しながらボタンをクリックすることで複数選択が可能です。
選択したら右クリックし、メニューから、Chains → Create Horizontal Chain を選択します。

すると、2つのボタンの間に鎖が現れ、横方向にグループ化されました。この状態を「チェインされた状態」といいます。

チェインされたビューたちの配置設定を変えることができるので確認してみましょう。
いずれかのボタンをクリックし、Cycle Chain Styleを選択します。

Cycle Chain Styleを選択するたびに、見た目が変化します。
SpreadまたはSpread Inside 状態で各ボタンの左右の制約をmatch_constraintに設定し、Weightedという状態にすることもできます。
今回はSpread状態にしましょう。

Packed
Spread
Spread Inside
Weighted

以上で、ビューのレイアウト調整が完了しました!

アプリの動作確認

アプリの動作確認

最後に、アプリを起動して見た目を確認してみましょう。
以下のような見た目でアプリが表示されていれば成功です!

おわりに

今回は、Androidアプリの見た目を作成しました。

次回は、ロジックを実装し、ボタンを押したら文字が表示される機能を作ります

残り2回を通して、プログラミング言語(Kotlin, Java)の文法を学びながらロジックを組み込んでいきましょう。

今回の勉強会はここまでです。お疲れさまでした!

次回の内容はこちら

この記事が気に入ったら
フォローしよう

最新情報をお届けします

Twitterでフォローしよう

おすすめの記事