Compose では、複数の修飾子を連鎖させて、コンポーザブルの外観を変更できます。これらの修飾子チェーンは、幅と高さの境界を定義するコンポーザブルに渡される制約に影響する可能性があります。
このページでは、連鎖された修飾子が制約にどのように影響し、コンポーザブルの測定と配置にどのように影響するかについて説明します。
UI ツリー内の修飾子
修飾子が相互にどのように影響するかを理解するには、コンポーズ フェーズ中に生成される UI ツリーにどのように表示されるかを確認すると役に立ちます。詳細については、構成のセクションをご覧ください。
UI ツリーでは、修飾子をレイアウト ノードのラッパー ノードとして可視化できます。
コンポーザブルに複数の修飾子を追加すると、修飾子のチェーンが作成されます。複数の修飾子を連結すると、各修飾子ノードは残りのチェーンとその中のレイアウト ノードをラップします。たとえば、clip
修飾子と size
修飾子を連結すると、clip
修飾子ノードが size
修飾子ノードをラップし、この修飾子ノードが Image
レイアウト ノードをラップします。
レイアウト フェーズでは、ツリーをたどるアルゴリズムは同じままですが、各修飾子ノードもアクセスされます。これにより、修飾子は、ラップする修飾子またはレイアウトノードのサイズ要件と配置を変更できます。
図 2 に示すように、Image
コンポーザブルと Text
コンポーザブルの実装自体は、単一のレイアウト ノードをラップする修飾子のチェーンで構成されています。Row
と Column
の実装は、単に子を配置する方法を記述するレイアウト ノードです。
まとめ
- 修飾子は、単一の修飾子またはレイアウト ノードをラップします。
- レイアウトノードは、複数の子ノードをレイアウトできます。
以降のセクションでは、このメンタルモデルを使用して修飾子の連鎖と、それがコンポーザブルのサイズに及ぼす影響について説明します。
レイアウト フェーズの制約
レイアウト フェーズでは、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
はこれらの境界に従い、300
×200
のサイズを報告します。このサイズはツリー全体に渡されます。
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
はこれらの制約を遵守し、100dp
×100
のサイズを報告します。padding
修飾子はすべてのサイズに10dp
を追加するため、報告される幅と高さが20dp
増加します。- 描画フェーズでは、
clip
修飾子が120dp
によって120
のキャンバスに作用します。そのため、そのサイズの円マスクが作成されます。 padding
修飾子は、すべてのサイズでコンテンツを10dp
分インセットするため、キャンバスのサイズは100dp
分小さくなり100
になります。Image
がそのキャンバスに描画されます。画像は120dp
の元の円に基づいてクリップされるため、出力は丸い結果ではありません。