ConstraintLayout Flowの紹介

ConstraintLayoutの2.0.0 alpha 5にFlow Virtual Layoutが導入されました🎉 Flowを使うことで、対象のViewを様々なルールで並べることができます。

メリットとしては、次のようなものがあります。

では、どのように書くのかを見ていきます。


1. 配置する方向を決める

android:orientationから、horizontal or verticalを指定できます。

<androidx.constraintlayout.widget.ConstraintLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <androidx.constraintlayout.helper.widget.Flow
    android:id="@+id/flow"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:orientation="horizontal"
    android:background="@android:color/white"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

  ...

これはorientationにhorizontalを持ちます。また、通常のViewのように各constraintsを指定し、配置することができます。

2. wrapModeを決める

flow_wrapModeで指定することができます。

wrapModeでは、どのようにViewを並べるかを指定でき、3種類のmodeがあります。

  1. none
    • 単純にsingle lineに並べる
  2. chain
    • 単純に順番に配置していく。その行(列)に収まらない場合は次の行(列)に配置する
  3. aligned
    • 各要素を整列するように配置していく。テーブルのようなイメージ
  <androidx.constraintlayout.helper.widget.Flow
    android:id="@+id/flow"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:orientation="horizontal"
    android:background="@android:color/white"
    app:flow_wrapMode="chain"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

これはchainで対象のViewを配置します。

3. 対象のViewを指定する

constraint_referenced_idsから指定します。

<androidx.constraintlayout.widget.ConstraintLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <androidx.constraintlayout.helper.widget.Flow
    android:id="@+id/flow"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:orientation="horizontal"
    app:flow_wrapMode="chain"
    android:background="@android:color/white"
    app:constraint_referenced_ids="title1,title2,title3"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

  <TextView
    android:id="@+id/title1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="chain1"
    android:textColor="@android:color/black"
    android:textSize="20sp" />

  <TextView
    android:id="@+id/title2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="chain2"
    android:textColor="@android:color/black"
    android:textSize="20sp" />

  <TextView
    android:id="@+id/title3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="chain3"
    android:textColor="@android:color/black"
    android:textSize="50sp" />

  ...

この場合、「title1、title2、title3」が対象のViewになります。また、これらのViewはhorizontalの方向に、chainで順々に配置されます。

4. その他、細かい調整

対象のView間のマージンや、行(列)の最大数、Viewの配置場所などの細かい部分の指定ができます。

次にMotionLayoutとFlowの使いかたについて見ていきます。

MotionLayout

これは通常のMotionLayoutの使い方と一緒です。Flowの値を変更してあげればよいです。

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:motion="http://schemas.android.com/apk/res-auto">

  <Transition
    android:id="@+id/transition"
    motion:constraintSetEnd="@+id/end"
    motion:constraintSetStart="@+id/start"
    motion:duration="1000" />

  <ConstraintSet android:id="@+id/start">
    <Constraint
      android:id="@id/flow"
      android:layout_width="0dp"
      android:layout_height="0dp"
      android:orientation="horizontal"
      motion:layout_constraintBottom_toBottomOf="parent"
      motion:layout_constraintEnd_toEndOf="parent"
      motion:layout_constraintStart_toStartOf="parent"
      motion:layout_constraintTop_toTopOf="parent" />
  </ConstraintSet>

  <ConstraintSet android:id="@+id/end">
    <Constraint
      android:id="@id/flow"
      android:layout_width="200dp"
      android:layout_height="0dp"
      android:orientation="vertical"
      motion:layout_constraintBottom_toBottomOf="parent"
      motion:layout_constraintEnd_toEndOf="parent"
      motion:layout_constraintStart_toStartOf="parent"
      motion:layout_constraintTop_toTopOf="parent" />
  </ConstraintSet>
</MotionScene>

こんな感じのアニメーションになります。

まとめ

参考

Written by
あんどろいどでぃべろっぱぁー🍎