ConstraintLayoutの制約の考え方とレイアウトテンプレート【Androidアプリ開発】

Androidアプリ開発入門

制約の概要

レイアウトはAndroid studioのレイアウトエディタで操作してる人が多いと思いますが、ConstraintLayoutの基本概要を書いていきます。

ビューはconstraintLayoutなどのレイアウトを定義するクラスでビューを配置していきます。ビューを配置したら制約を設定する必要があります。

制約とは配置したビューを自由に動かさないようにする(制約する)枠や線を決めて水平方向もしくは垂直方向に制限をかける設定といった所でしょうか。極端な例をあげると水平方向のみ制約した場合、水平方向は制限されて動けなくなります。一方垂直方向へは自由に動けますが設定した枠や線までの範囲内となります。(注:この例は実用的ではありません)

constraintLayout制約したビューのイメージ図

制約の考え方

最初に制約する枠や線を決めます。これは親のレイアウトや他のビューなどがあります。次に基準になる辺やラインを決めます。これはビューの4つの辺と真ん中あたりにあるベースラインになります。次に水平方向または垂直方向のどちらに制限するかを決めます。場合によりますが次に左右上下のどちらにするのかを決めます。水平方向なら左右、垂直方向なら上下です。水平方向なら左、垂直方向なら上が多いです。次に相対位置からどれくらいの幅や高さをとるのか決めます。

  1. 制限する枠や線を決める
  2. 基準となるビューの辺を決める
  3. 制限する方向を決める(水平方向か垂直方向)
  4. 制限する方向を決める(左右か上下)
  5. どれくらいの幅や高さに合わせるか決める

例えば下図の例だと親のレイアウトを枠としてビューの左辺を基準の辺として水平方向に左に制約がかかります。つまりボタンビューの左側から親のレイアウトの左側までを制約しますよということです。基準になる辺から親のレイアウトの相対位置の幅(矢印の部分)を設定するとその位置で固定されます。一方垂直方向は設定されていないので、エミュレーターなどで見ると一番上に来てしまいます。真ん中辺りに設定するには垂直方向の制約もする必要があります。

constraintLayout制約の考え方イメージ図

この例は相対位置のレイアウトになります。配置するビューは複数になる事が多いと思うのでそれも見ていきましょう。

複数ビューのレイアウト配置の例

色々な考え方がありますが、まずAは親のレイアウトに対して水平方向にセンタリングの制約します。BはAに対して位置揃えの制約をします。CはBに対して水平方向に制約をします。こんな感じ1個づつ考えていくわけです。センタリングだの位置揃えだのと出て来ましたが、実はレイアウトのテンプレートがあってそれを組み合わせて設定していきます。レイアウトのテンプレートについては後述します。

制約を間違えるとレイアウトが大幅に崩れてしまう事があります。ご存知の通りスマホは多くの画像サイズが存在します。また横にするとサイズが変わったりしますよね。色々な画面サイズにある程度対応出来るようにレイアウトを考える必要があります。このような考えをレスポンシブユーザーインタフェース(レスポンシブUI)といいます。下図は違う画面サイズで見た時にレイアウトが崩れた例ですが、Bを親レイアウトの左辺に制約して、Cを親レイアウトの右辺に制約すると、良いのか悪いのかBC間の幅が広がります。

崩れたレイアウトの例

制約はビューごとに水平方向か垂直方向を最低1つ設定する決まりになっています(ビューの種類によって異なる)。Android studioのレイアウトエディタから設定した場合には制約がないとエラーが表示されます。このエラーを無視してコンパイルしてもコンパイルエラーにはならずに全てのビューが端末画面の左端0.0の位置で表示されます。

制約する枠やラインの種類

親のレイアウト、他のビュー、位置揃え、ガイドライン、バリアがあります。

constraintLayout制約の種類
親のレイアウト親のレイアウトはConstraintLayoutです。親の4辺が相対位置になります。全てのレイアウトが使える。
他のビュー他のビューの4辺を相対位置にします。Bを制約した場合、Aが相対位置です。相対位置、マージン、ベースライン、循環配置、寸法拘束のレイアウトが使える。
位置揃えのビューの4辺を相対位置にします。Bを制約した場合、Aと位置を揃えます。
オフセットを使用した位置揃えやベースラインを使用した位置揃えなどがあります。
ガイドライン非表示の水平・垂直軸のガイドラインを相対位置とします。
バリアガイドラインと同じですが、こちらはAかBの長さに合わせてラインを引きます。
(Cを制約した場合)

基準になる辺やライン

基準になる辺やラインにはビューの4つの辺と真ん中あたりにあるベースラインがあります。平行方向へ制約する場合、右辺は制約するビューのstartにもなり、左辺は参照するビューのendにもなります。Start・Endの組合せで使うのが一般的です。

constraintLayout制約の基準になる辺

グループ

ビューはグループ化して表示・非表示を設定できます。使い方としてはグループを作り、非表示にしたいビューが複数有った時などにグループ化すると便利です。複数のグループが同じビューを参照出来ますがその場合の可視状態は最後のグループに書かれている値が適用されます。

ビューグループ階層イメージ図

プレースホルダー

プレースホルダーとは既存のオブジェクトを配置できる仮想オブジェクトの事です。ビューをレイアウト配置してプレースホルダーオブジェクトを表示したりできます。プレースホルダーオブジェクトにsetContentIdID()を使用してビューIDを指定してる場合コンテンツビューになり他のビューと同じ様に制約します。プレースホルダーのコンテンツビューが画面に存在する場合は元の場所から消えたものとして扱われます。つまり、0dbとして扱われる。(View.GONEで非表示にした時と同じ扱い)

プレースホルダーの制約イメージ図

レイアウトテンプレートの種類

レイアウトのテンプレート的なものです。

相対位置

親のレイアウトか他のビューに対して相対的に配置します。水平軸(left・start、right・start)と垂直軸(top、bottom、baseline)に制約出来ます。

相対位置のレイアウト配置のイメージ図

マージン

マージン

上下左右のマージンの制約をします。

レイアウト配置マージンの例

ビューを非表示(GONE)にした時のマージン(可視性の動作)

GONEはsetVisibility(View.GONE)メソッドまたはandroid:visibility = "gone"でビューを非表示にする事ができます。これを指定した時のマージンはどうなるかというと、非表示にしたビューは0dbとなって無いものとして扱われます。下図は非表示にしたビューAに100dbの制約、Bに20dbの制約をしています。しかしAは0dbとして扱われるのでBのレイアウトが意図したものにならない場合もあります。こうしたときGONEのビューに制約した時のマージンを再定義する事ができます。
ビューを非表示にしたと時の制約の例

ベースライン

他のビューのベースラインに合わせて位置を揃えます。

レイアウト配置ベースラインの例

バイアスのセンタリング

親のレイアウトに対して水平・垂直軸にセンタリングします。

レイアウト配置センタリングの例

バイアス

センタリングより片側に傾かせたい時に使用します。

レイアウト配置biasの例

円形(Circular)配置

ビューを円形上に配置します。円の中心のにあるビューと他のビューの中心に対して角度と距離で制約します。

レイアウト配置のCircularの例

サイズの制約

ConstraintLayoutの大きさの制限

ビューの最小サイズと最大サイズを定義できます。

ビューの大きさの設定

ビューの縦横のサイズは通常dp単位で指定しますが、パーセント比率やアスペクト比率(1:1、16:9など)で設定する事も可能です。

チェーン

2つ以上のビューがそれぞれ双方向で制約してる場合チェーンと呼ばれるものになります(水平軸・垂直軸)。チェーンの最初のビューを『ヘッド』と呼び、ヘッドに設定された属性によって制御されます。

レイアウト配置のチェーンの例

チェーンのスタイル

チェーンのスタイルはSpread・Weighted・Packedの3種類があり、デフォルトのスタイルはSpreadチェーンになります。

レイアウト配置のチェーンスタイルの例

gradleの依存関係を設定する

ConstraintLayoutのbuild.gradleの依存関係は下記の様に宣言します。Android Studioでは自動でこの設定が入ります。

dependencies {
    implementation "androidx.constraintlayout:constraintlayout:1.1.3"
}

レイアウトファイル(XML)で作ります

実際に作って見ないとわからないと思いますが色々試して見ると良いと思います。これらのレイアウトはレイアウトファイル(XML)に記述していきますが、Android Studioではレイアウトエディタがあり視覚的に操作することが可能です。それぞれ別の記事でやり方を書いてるので参考にして下さい。