Contents
Dealing with box constraints
Note:フレームワークがbox constraintsに関連する問題を検出した場合は、このページに移動する可能性があります。
Note:Flutterでの制約(constraints)、サイズ設定(sizing)、および配置(positioning)の仕組みに混乱している場合は、
2020/10/21 Flutter : Understanding constraintsの訳パート1
2020/10/21 Flutter : Understanding constraintsの訳パート2(Example3〜10)
2020/10/21 Flutter : Understanding constraintsの訳パート3(Example11〜20)
を参照してください。
Flutterにおいてウィジェットは、基礎となるRenderBoxオブジェクトによってレンダリングされます。
レンダリングボックスには親(ウィジェット)から制約が与えられ、それらの制約内で自身のサイズが決定されます。
Constraints(制約)は、
width(幅)の最小値・最大値、height(高さ)の最小値・最大値
から構成されます。
Sizeは特定のwidth(幅)とheight(高さ)から構成されます。
一般に、constraints(制約)の処理方法に関して、3種類のボックスがあります。
- できるだけ大きくしようとするもの。 たとえば、CenterやListViewで使用されるボックス。
- 子ウィジェットと同じサイズになろうとするもの。 たとえば、TransformやOpacityで使用されるボックス。
- 特定のサイズになろうとするもの。 たとえば、ImageやTextで使用されるボックス。
Containerなどの一部のウィジェットは、コンストラクターの引数に基づいてタイプが異なります。(タイプというのは上に挙げた三種類のタイプのことだと思われる。)
Containerの場合、デフォルトではできるだけ大きくなろうとしますが、たとえばwidth(幅)を指定すると、それを尊重して特定のサイズにしようとします。
↓のようにwidth,heightを指定しない場合(親ウィジェットの範囲内で)できるだけ大きくなろうとする。
home: Container(),
↓のようにwidth,heightを指定するとその大きさになろうとする。
home: Container( width:50, height:50, ),
それに対して、例えばRowやColumn(flex boxed)は、以下の「Flex」セクションで説明するように、与えられた制約に基づいて異なります。
constraintsは時に”tight”な場合があります。
「constraintsが”tight”」とは、レンダリングボックスでサイズを決定する余地がない状態です。(たとえば、最小幅と最大幅が同じ場合、幅が”tight”(タイト)であると言われます)。
constraintsが”tight”な例として、RenderViewクラスに含まれるAppウィジェットが挙げられます。
アプリケーションのbuildメソッドで返される子ウィジェットに使用されるボックスには、アプリケーションのコンテンツ領域(通常は画面全体)を厳密に埋めるように強制する制約が与えられます。
Flutterのボックスの多く、特にsingle childなウィジェットのボックスは、制約を子供に渡します。(single childなウィジェットとは、子ウィジェットを一つだけ保持するウィジェット、ということ。)
つまり、アプリケーションのレンダリングツリーのルートで多数のボックスを相互にネストすると、全ての子ウィジェットが”tight”なconstraints(制約)を受けて、すべての子ウィジェットが正確に相互にフィットします。
一部のボックスは制約を緩めます(loose)。つまり、最大値は維持されますが、最小値は削除されます。 たとえば、Centerウィジェットがこの例にあたります。
Unbounded constraints(無制限の制約)
特定の状況では、ボックスに与えられるconstraints(制約)が無制限(unbounded)、または無限(infinite)である、という場合もあります。
これは、最大幅または最大高さのいずれかがdouble.infinityに設定されていることを意味します。
可能な限り大きくしようとするボックスは、unbounded constraints(無制限の制約)が与えられた場合はうまく機能せず、デバッグモードでは、このような組み合わせはこのファイルを指す例外をスローします。
レンダーボックスがunbounded constraints(無制限の制約)を受ける最も一般的なケースは、flex boxed(フレックスボックス)内に配置されている場合です。
flex boxed(フレックスボックス)は、RowやColumn、ListViewや他のScrollViewのサブクラスです。
In particular, ListView
tries to expand to fit the space available in its cross-direction (for example, if it’s a vertically-scrolling block, it tries to be as wide as its parent).
特に、ListViewは、そのcross axis方向で使用可能なスペースにfitするように拡張しようとします(たとえば、垂直スクロールブロックの場合、親と同じ幅になろうとします)。
If you nest a vertically scrolling ListView
inside a horizontally scrolling ListView
, the inner one tries to be as wide as possible, which is infinitely wide, since the outer one is scrollable in that direction.
垂直方向にスクロールするListViewを水平方向にスクロールするListView内にネスト(配置)すると、外側の水平ListViewはその水平方向にスクロール可能であるため、内側のListViewは可能な限り、つまり無限に広くなろうとします。
外側の水平ListViewは水平方向に関して(つまり子のwidth方向に関して)、unbounded constraintを与える、ということ。
Flex
Flex boxed(フレックスボックス)それ自体(RowやColumn)は、与えられた方向における制約が
bounded constraints
か、
unbounded constraints
か
によって振る舞いが異なります。
bounded constraintsでは、その与えられた方向でできる限り大きくなろうとします。
unbounded constraintsでは、フレックスボックスは子ウィジェットをその方向においてフィットさせようとします。 この場合、子ウィジェットのflexを0(デフォルト)以外に設定することはできません。
ウィジェットライブラリでは、これは、フレックスボックスが別のフレックスボックス内またはscrollable内にある場合、Expandedを使用できないことを意味します。 そうした場合、このドキュメントを指し示す例外メッセージが表示されます。
cross direction(クロス方向)、つまり
Columnにおけるwidth(垂直方向のflex)
Rowにおけるheight(水平方向のflex)
では、これらはunboundedな状態は許されません。(制限が必要、ということ。)
そうでなければ、彼らは子供たちを合理的に配置させることができません。
(そういう場合、例外がスローされる)
参考
https://flutter.dev/docs/development/ui/layout/box-constraints