Compose では、複数の修飾子を連結して、コンポーザブルの外観を変更できます。これらの修飾子チェーンは、幅と高さの境界を定義するコンポーザブルに渡される制約に影響を与える可能性があります。
このページでは、連鎖修飾子が制約にどのように影響し、ひいてはコンポーザブルの測定と配置にもたらす影響について説明します。
UI ツリーの修飾子
修飾子が互いにどのように影響し合うかを理解するには、コンポジション フェーズで生成される UI ツリーで修飾子がどのように表示されるかを可視化すると便利です。詳細については、コンポジション セクションをご覧ください。
UI ツリーで、修飾子をレイアウト ノードのラッパーノードとして可視化できます。
コンポーザブルに複数の修飾子を追加すると、修飾子のチェーンが作成されます。複数の修飾子を連結すると、各修飾子ノードがチェーンの残りとレイアウト ノードをラップします。たとえば、clip
修飾子と size
修飾子を連結すると、clip
修飾子ノードが size
修飾子ノードをラップし、さらに Image
レイアウト ノードがラップされます。
レイアウト フェーズでは、ツリーを走査するアルゴリズムは変わりませんが、各修飾子ノードもアクセスされます。このようにして、修飾子は、ラップする修飾子またはレイアウト ノードのサイズ要件と配置を変更できます。
図 2 に示すように、Image
コンポーザブルと Text
コンポーザブル自体の実装は、1 つのレイアウト ノードをラップする修飾子のチェーンで構成されます。Row
と Column
の実装は、単に子のレイアウト方法を記述するレイアウト ノードです。
まとめ
- 修飾子は、1 つの修飾子またはレイアウト ノードをラップします。
- レイアウト ノードは複数の子ノードをレイアウトできます。
以降のセクションでは、このメンタルモデルを使用して、修飾子の連鎖について推論する方法と、それがコンポーザブルのサイズにどのように影響するかについて説明します。
レイアウト フェーズでの制約
レイアウト フェーズでは、3 ステップのアルゴリズムに従って、各レイアウト ノードの幅、高さ、x、y 座標を検索します。
- 子を測定する: ノードはその子(存在する場合)を測定します。
- 独自のサイズを決定する: これらの測定値に基づいて、ノードが独自のサイズを決定します。
- 子ノードを配置する: 各子ノードは、ノード自体の位置を基準として配置されます。
Constraints
は、アルゴリズムの最初の 2 つのステップでノードに適したサイズを見つけるのに役立ちます。制約は、ノードの幅と高さの最小値と最大値を定義します。ノードがサイズを決定すると、測定されたサイズはこのサイズ範囲内になります。
制約のタイプ
制約は次のいずれかです。
- 有限: ノードの幅と高さに最大値と最小値があります。
- 制限なし: ノードのサイズに制限はありません。幅と高さの最大値は無限大に設定されています。
- 完全一致: ノードは正確なサイズ要件に従うように求められます。最小値と最大値は同じ値に設定されます。
- 組み合わせ: ノードは、上記の制約タイプの組み合わせに従います。たとえば、制約で幅を制限しながら最大高さを制限したり、厳密な幅を設定して高さを制限したりできます。
次のセクションでは、これらの制約を親から子に渡す方法について説明します。
制約を親から子に渡す方法
レイアウト フェーズでの制約で説明されているアルゴリズムの最初のステップでは、制約は UI ツリーの親から子へと下方に渡されます。
親ノードが子を測定する場合、これらの制約を各子に与え、許容される大きさを知らせます。次に、自身のサイズを決定するとき、自身の親から渡された制約に従います。
アルゴリズムの概要は次のとおりです。
- 実際に占有するサイズを決定するために、UI ツリーのルートノードはその子を測定し、同じ制約を最初の子に転送します。
- 子が測定に影響しない修飾子の場合、制約は次の修飾子に転送されます。測定に影響する修飾子に達しない限り、制約は修飾子チェーンにそのまま渡されます。それに応じて制約のサイズが変更されます。
- 子を持たないノード(「リーフノード」と呼ばれます)に到達すると、渡された制約に基づいてサイズを決定し、解決されたサイズを親に返します。
- 親は、この子の測定に基づいて制約を適応させ、調整された制約を使用して次の子を呼び出します。
- 親のすべての子が測定されると、親ノードは独自のサイズを決定し、それを自身の親に伝えます。
- このようにして、ツリー全体を深度優先で走査します。最終的には、すべてのノードのサイズが決定され、測定ステップは完了します。
詳細な例については、制約と修飾子の順序の動画をご覧ください。
制約に影響する修飾子
前のセクションでは、一部の修飾子が制約サイズに影響する可能性があることを学習しました。以降のセクションでは、制約に影響する特定の修飾子について説明します。
size
修飾子
size
修飾子は、コンテンツの推奨サイズを宣言します。
たとえば、次の UI ツリーは、200dp
によって 300dp
のコンテナにレンダリングされます。制約は制限付きで、幅は 100dp
~300dp
、高さは 100dp
~200dp
の範囲で指定できます。
size
修飾子は、渡された値と一致するように受信制約を調整します。この例では、値は 150dp
です。
幅と高さが最小制約の境界よりも小さいか、最大の制約の境界より大きい場合、修飾子は渡された制約を遵守しながら、渡された制約に可能な限り近づけます。
複数の size
修飾子を連結しても機能しません。最初の size
修飾子は、最小制約と最大制約の両方を固定値に設定します。2 番目のサイズ修飾子が小さいサイズまたは大きいサイズをリクエストした場合でも、渡された正確な境界に従う必要があるため、これらの値はオーバーライドされません。
requiredSize
修飾子
ノードで受信制約をオーバーライドする必要がある場合は、size
ではなく requiredSize
修飾子を使用します。requiredSize
修飾子は受信制約を置き換え、指定されたサイズを正確な境界として渡します。
サイズがツリーに戻されると、子ノードは使用可能なスペースの中央に配置されます。
width
修飾子と height
修飾子
size
修飾子は、制約の幅と高さの両方を適応させます。width
修飾子を使用すると、固定の幅を設定できますが、高さは固定せずに済みます。同様に、height
修飾子を使用すると、高さを固定して設定できますが、幅は決まらないでください。
sizeIn
修飾子
sizeIn
修飾子を使用すると、幅と高さの正確な最小制約と最大制約を設定できます。制約をきめ細かく制御する必要がある場合は、sizeIn
修飾子を使用します。
例
このセクションでは、連鎖修飾子を使用した複数のコード スニペットからの出力を示します。
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
このスニペットにより、次の出力が生成されます。
fillMaxSize
修飾子は制約を変更して、最小の幅と高さの両方を最大値(幅は300dp
、高さは200dp
)に設定します。size
修飾子が50dp
のサイズを使用する場合であっても、入力される最小制約に従う必要があります。そのため、size
修飾子は200
による300
の正確な制約境界も出力し、size
修飾子で指定された値は無視されます。Image
はこれらの境界に従い、200
のサイズ300
を報告します。これはツリーの最後まで渡されます。
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
このスニペットにより、次の出力が生成されます。
fillMaxSize
修飾子は制約を適応させて、最小の幅と高さの両方を最大値に設定します(幅は300dp
、高さは200dp
)。wrapContentSize
修飾子は最小制約をリセットします。したがって、fillMaxSize
は固定制約になりましたが、wrapContentSize
は制限付き制約にリセットします。次のノードが再度スペース全体を占有することも、スペース全体よりも小さくすることもできます。size
修飾子は、制約を50
の最小値と最大値に設定します。Image
は50
×50
のサイズに解決され、size
修飾子はそれを転送します。wrapContentSize
修飾子には特別なプロパティがあります。子を取得し、渡された使用可能な最小境界の中央に配置します。したがって、モデルが親に伝えるサイズは、渡された最小境界と等しくなります。
3 つの修飾子を組み合わせることで、コンポーザブルのサイズを定義し、親の中心にすることができます。
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
このスニペットにより、次の出力が生成されます。
clip
修飾子は制約を変更しません。padding
修飾子は、最大制約を下げます。size
修飾子は、すべての制約を100dp
に設定します。Image
はこれらの制約に従い、サイズ100
を100dp
単位で報告します。padding
修飾子はすべてのサイズに10dp
を追加するため、レポートされる幅と高さが20dp
だけ増加します。- 描画フェーズでは、
clip
修飾子が120dp
による120
のキャンバスに作用します。そのため、そのサイズの円マスクを作成します。 - 次に、
padding
修飾子がすべてのサイズでコンテンツを10dp
で挿入し、キャンバス サイズを100dp
だけ100
に小さくします。 Image
がそのキャンバスに描画されます。画像は120dp
の元の円に基づいてクリップされるため、出力は非円形の結果になります。