今回読んだページ
個人的なまとめ
- 「制約」は最小・最大の幅と高さで構成され、「サイズ」は特定の幅と高さで構成されている。
- 制約の処理方法に関しては3種類のボックスがある
- 可能な限り大きくなろうとするもの。例えば、
Center
やListView
によって使われるボックス。 - 自身のchildrenと同じ大きさになろうとするもの。例えば、
Transform
やOpacity
によって使われるボックス。 - ある特定のサイズになろうとするもの。例えば、
Image
やText
によって使われるボックス。
- 可能な限り大きくなろうとするもの。例えば、
-
Center
のように、制約を緩和させる(最大値はそのままで、最小値を0にする)widgetがある - Unbouded box(無制限のボックス)を使う際は注意が必要
Dealing with box constraints
Note: フレームワークがBox Constraintに関係する問題を検出したとき、このページが表示されることがあります。
Note: Flutterでの制約、サイズ変更、配置の仕組みについて混乱している場合は、Understanding constraintsを参照してください。
Flutterでは、Widgetsはそれらの基礎となるRenderBox
オブジェクトによってレンダリングされます。
Render boxesはそれらの親から制約を与えられ、その制約の中で自身のサイズを調整します。
制約は最小・最大の幅と高さで構成され、サイズは特定の幅と高さで構成されています。
一般的には、制約の処理方法に関して、3種類のボックスがあります:
- 可能な限り大きくなろうとするもの。例えば、
Center
やListView
によって使われるボックス。 - 自身のchildrenと同じ大きさになろうとするもの。例えば、
Transform
やOpacity
によって使われるボックス。 - ある特定のサイズになろうとするもの。例えば、
Image
やText
によって使われるボックス。
例えば、Container
のようないくつかのWidgetsは、コンストラクタの引数に基づいてタイプが異なります。
Container
の場合、デフォルトではできるだけ大きくなろうとしますが、例えばwidth
を与えた場合、それを優先して特定のサイズになろうとします。
例えば、Row
やColumn
(flex boxes)といった他のwidgetは、Flexセクションで後述するように、受け取った制約に基づいて変化します。
制約は「厳しく」なる場合があります。つまり、レンダーボックスがサイズを決める余地がなくなります(例えば、最小と最大の幅が同じ場合、厳しい幅を持つと言います)。
この例は、RenderView
classに含まれているApp
widgetです。
アプリケーションのbuild
関数によって返されたchildが使用するボックスには、アプリケーションのコンテンツ領域を正確に埋めるように(たいていはスクリーン全体)強制する制約が与えられます。
Flutterのボックスの多く、特に1つのchildしか持たないボックスは、自身の制約をchildrenに渡します。
つまり、アプリケーションのレンダーツリーのRootで、たくさんのボックスを入れ子にした場合、これらは厳しい制約によって強制され、互いにフィットします。
一部のボックスは制約を緩和します。つまり、最大値は維持されますが、最小値は削除されます。
例えば、Center
です。
補足
MaterialApp
のhome
に直接Container
を使ってwidth, height
を指定しても、適用されない。
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Container(
width: 50,
height: 50,
color: Colors.cyan
),
)
);
}
Center
などでラップすると、制約が緩められ、Container
に指定した制約が適用されるようになる。
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
home: Center(
child: Container(
width: 50,
height: 50,
color: Colors.cyan
),
)
)
);
}
Unbounded constraints
ある状況では、ボックスに与えられた制約は、「無制限」あるいは無限になります。
つまり、最大の幅または最大の高さにdouble.INFINITY
がセットされるということです。
無制限の制約が指定されている場合、できるだけ大きくなろうとするボックスは有効に機能せず、
デバッグモードでは、そのような組み合わせはそのファイルを指す例外を投げます。
レンダーボックスが無制限の制約を持っているとわかる最も一般的なケースは、flex boxes(Row
やColumn
)の中や、スクロール可能な領域(ListView
や他のScrollView
subclasses)内にあります。
特に、ListView
は、利用可能なスペースを埋めようと、そのcross-directionに広がろうとします。(例えば、垂直方向のスクロールブロックの場合、親と同じ幅になろうとします。)
垂直スクロールのListView
を水平スクロールのListView
にネストする場合、中のものはできるだけ広くなり、外のものはその方向にスクロールできるため、無限に広くなります。
Flex
Flex boxes(Row
とColumn
)自体の動作は、それらが指定された方向に境界のある制約なのか無制限の制約なのかによって異なります。
境界がある制約の場合、その方向にできるだけ大きくなろうとします。
境界がない制約の場合、childrenをその方向にフィットさせようとします。
この場合childrenのflex
を0(デフォルト値)以外に設定することはできません。
Widget Libraryでは、これは、Flex boxが他のFlex boxまたはスクロール可能なオブジェクト内にある場合、Expanded
を使用できないことを意味します。
そうすると、このドキュメント示す例外メッセージが表示されます。
cross-direction、例えば、Column
(垂直のflex)の幅やRow
(水平のflex)の高さでは、決して境界なしにしてはいけません。
そうでなければ、それらはchildrenを合理的に整列させることができません。