ConstraintLayout入門その2 - センタリング、あるいはbias

ConstraintLayoutを使用するための設定については、[前回記事](https://qiita.com/yamadacsa/items/a4fcf4de9982111cdb7c)をご覧ください。

## ConstraintLayoutのセンタリング

FrameLayoutの子Viewを親Viewの中央に置くときは ```android:layout_gravity``` に ```center_horizontal```, ```center_vertical``` などの値を設定します。RelativeLayoutの子Viewを親Viewの中央に置くときは ```android:layout_centerHorizontal```, ```android:layout_centerVertical``` などの値を ```"true"``` に設定します。
これらに対し、ConstraintLayoutでのセンタリングは、「Viewの上下端もしくは左右端を同時に制約する」、という、いささか手間のかかる方式を用います。

```xml:activity_main.xml
<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">

    <ImageView
        android:id="@+id/viewControlled"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintVertical_bias="0.15"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.6"
        android:background="@color/colorAccent"
        android:src="@drawable/ic_launcher_foreground" />

    ...

</androidx.constraintlayout.widget.ConstraintLayout>
```

## 表示結果

上記XMLは以下のように表示されます。

<img width="360" alt="表示結果" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221967/0c2c8318-904e-89be-5b04-ac905ad83cef.png">

```app:layout_constraintTop_toTopOf```,  ```app:layout_constraintBottom_toBottomOf``` に ```"parent"``` を設定し、上下端が親Viewに制約されるようにします。これは素直に読むと、子Viewが親Viewと同じ高さに引き伸ばされそうにも思えますが、ここでは ```android:layout_height``` が ```"wrap_content"``` となっていることから、ImageViewは伸びません。伸びない代わりに、ImageViewは上からも下からも引っ張られ、バランスの取れた位置に設定されます。このバランスを決定するのが ```app:layout_constraintVertical_bias``` の値です。

## bias

```app:layout_constraintVertical_bias``` には0から1までの値を小数で設定できます。省略することもでき、省略されたときのデフォルト値は0.5となります。0.5に設定した場合、垂直方向の位置はちょうど中央に設定され、FrameLayoutやRelativeLayoutで行うセンタリングと同じ結果になります。

ConstraintLayoutでは、biasの設定を加えることにより、FrameLayoutやRelativeLayoutよりも柔軟な位置取りを可能にしています。 ```app:layout_constraintVertical_bias``` が0のときは上端の制約に張りつきます（下端の制約を省略したのと同じ結果になります）。```app:layout_constraintVertical_bias``` が1のときは下端の制約に張りつきます（上端の制約を省略したのと同じ結果になります）。
0と1の間の値を設定すれば、これらの中間の位置取りを行えます。

ほぼ同様に、水平方向の位置取りは ```app:layout_constraintHorizontal_bias``` で設定し、省略ないし0.5を設定すれば水平方向のセンタリングが行えます。 ```app:layout_constraintHorizontal_bias``` が0のときは 'Left' もしくは 'Start' に設定した制約に張りつき、1のときは 'Right' もしくは 'End' に設定した制約に張りつきます。0と1の間の値を設定すれば、中間の位置取りを行えます。

## right to leftレイアウト

activity_main.xml のConstraintLayoutで ```android:layoutDirection="rtl"``` の設定を加えると、right to leftレイアウトに変わって左右が反転しますが、上下左右の空白部分については今回のコードは対応が甘いので少し表示が崩れます。

## サンプルコード

biasの仕様にあまり興味がない開発者には、ひとまずConstraintLayoutでセンタリングを行う要領をつかんでいただければ充分です。ConstraintLayoutは多機能かつ複雑ですので、一気に使い方をマスターしようとするよりも、少しずつ習得して使える場面を徐々に増やしていくことをお勧めします。

今回のサンプルコードは以下のリポジトリにあります。
https://github.com/csayamada/ConstraintLayout2

サンプルコードでは、 activity_main.xml にて ```app:layout_constraintVertical_bias```, ```app:layout_constraintHorizontal_bias``` の値を変更してビルドしアプリを実行すると、表示結果の上下左右の空白のスケールと比率が自動的に表示されるようになっています。表示結果から、biasの値が上と下の空白の比率、および左と右の空白の比率を決定していることがわかります。

## 柔軟性

上下端、左右端の制約には ```"parent"``` のほかに他の子ViewのIDを指定することができ、従来の親View内のセンタリング以上の表現、たとえば複数の子Viewと位置を合わせたり、biasの設定との組み合わせるなどといった、RelativeLayoutなどよりも柔軟な位置取りが行えます。
制約には```app:layout_constraintTop_toBottomOf```, ```app:layout_constraintStart_toEndOf``` などを使うこともでき、LinearLayoutのネストなどを行わずに子Viewを整列させたりできます。

## 参考文献

[Constraintlayout | Android デベロッパー | Android Developers](https://developer.android.com/jetpack/androidx/releases/constraintlayout?hl=ja)
[ConstraintLayout | Android Developers](https://developer.android.com/reference/androidx/constraintlayout/widget/ConstraintLayout)
[Understanding VectorDrawable pathData commands in Android](https://medium.com/@ali.muzaffar/understanding-vectordrawable-pathdata-commands-in-android-d56a6054610e)