ConstraintLayoutを使いたい - 基本編【Android】

# Androidアプリのレイアウト作り
* LinearLayout
* RelativeLayout
* ConstraintLayout

...などなど、
Androidのレイアウトの作り方、いろいろありますよね。

個人的にはConstraintLayoutが好きなのですが、
後から追加されたレイアウトということもあり、昔からAndroid開発をやっている方からすると、
「新しく覚えなくてもLinearLayoutやRelativeLayoutでいいじゃん:thinking:」と思うことがあるようです。

そんな方に向けて、**「ConstraintLayoutはいいぞ」**を伝えられる記事があったらいいなと思い、
この記事を書きました。

# ConstraintLayoutのいいところ
* レスポンシブな画面を作りやすい
* ネストの必要がないので処理が早くなる（らしい）

以下の記事が参考になります。
[ConstraintLayout がもたらすパフォーマンスのメリットを理解する - Google Developers Japan](https://developers-jp.googleblog.com/2017/09/understanding-performance-benefits-of.html)

# 使い方の基本
## Constraint(制約)を追加する
ConstraintLayoutの基本の考え方です。
View1つの各辺に対し、制約をつけていきます。他のViewとの関係性をつけていくイメージです。

### 書き方
```
app:layout_constraint[自分の辺]_to[相手の辺]Of="@+id/相手のid"
```

[ ]の部分には下の画像の言葉が入ります。
<img width="360" alt="スクリーンショット 2019-12-16 23.26.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/cc51acf9-cf4e-b658-0985-ac6e3f05bb38.png">

**Q. なぜLeft＝Start、Right＝Endなの？
A. LTRモード(Left To Right)だから。**

Left,RightでもOKですが、Start,Endにしておくと
端末をRTLモード（アラビア語などの右読み言語）に変更した場合に左右を逆向きにしてくれます。

### 使用例
このように2つ並んだ状態を作る場合には少なくとも以下の制約をつけます
<img width="380" alt="スクリーンショット 2019-12-16 23.55.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/6c30542d-9ba3-91a9-998a-aa089727a5af.png">

* View Aに制約をつける場合
    * `layout_constraintTop_toTopOf="@+id/ViewB"`
    * `layout_constraintEnd_toStartOf="@+id/ViewB"`

* View Bに制約をつける場合
    * `layout_constraintTop_toTopOf="@+id/ViewA`
    * `layout_constraintStart_toEndOf="@+id/ViewA`

両方のViewに制約をつけても問題はないです。
Topの部分はBottomに変えても同じです。

**実際にActivityにボタンを2つ配置してみます。**
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/2742e2b0-01fe-05f5-d811-26f5925676ed.png" width="300">
この画面のxmlは以下のようになっています。

```activity_sample.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=".SampleActivity">

    <Button
        android:id="@+id/button_A"
        android:text="ボタンA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/button_B" />

    <Button
        android:id="@+id/button_B"
        android:text="ボタンB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="@+id/button_A"
        app:layout_constraintStart_toEndOf="@+id/button_A"
        app:layout_constraintEnd_toEndOf="parent"/>


</androidx.constraintlayout.widget.ConstraintLayout>
```
* ボタンAの制約
    * Top = 親のTopに合わせる
    * Start = 親のStartに合わせる
    * End = ボタンBのStartに合わせる
* ボタンBの制約
    * Top = ボタンAのTopに合わせる
    * Start = ボタンAのEndに合わせる
    * End = 親のEndに合わせる

ポイントは大きく分けて３つ。

1. 画面上部にボタンを配置する制約
2. ボタンAとボタンBの上部分を合わせる制約
3. ボタンを横につなげる制約

**並んだ方向すべてに制約をつけると、等間隔で並べることができます。**
（この場合は「親-ボタンA-ボタンB-親」が全てStart-Endの関係でつながっています。）

並んだViewの間隔を広げたりくっつけたりするときは「Chain」を使います。
が、それはまた別の記事として書こうと思います。

# 最後に
ConstraintLayoutはパッと見では（文字数多くて？）厄介に見えるかもしれませんが、
一度やってみるとそこまで敷居は高くないです。
むしろxmlがフラットになってきれいになるはず。
これから導入するところが少しでも増えてくれるといいなぁと思います。