0
0

More than 3 years have passed since last update.

Flutterの公式ドキュメントを読んで理解する 〜Building layouts/Dealing with box constraints〜

Posted at

今回読んだページ

個人的なまとめ

  • 「制約」は最小・最大の幅と高さで構成され、「サイズ」は特定の幅と高さで構成されている。
  • 制約の処理方法に関しては3種類のボックスがある
    • 可能な限り大きくなろうとするもの。例えば、CenterListViewによって使われるボックス。
    • 自身のchildrenと同じ大きさになろうとするもの。例えば、TransformOpacityによって使われるボックス。
    • ある特定のサイズになろうとするもの。例えば、ImageTextによって使われるボックス。
  • Centerのように、制約を緩和させる(最大値はそのままで、最小値を0にする)widgetがある
  • Unbouded box(無制限のボックス)を使う際は注意が必要

Dealing with box constraints

Note: フレームワークがBox Constraintに関係する問題を検出したとき、このページが表示されることがあります。

Note: Flutterでの制約、サイズ変更、配置の仕組みについて混乱している場合は、Understanding constraintsを参照してください。

Flutterでは、Widgetsはそれらの基礎となるRenderBoxオブジェクトによってレンダリングされます。
Render boxesはそれらの親から制約を与えられ、その制約の中で自身のサイズを調整します。
制約は最小・最大の幅と高さで構成され、サイズは特定の幅と高さで構成されています。

一般的には、制約の処理方法に関して、3種類のボックスがあります:

  • 可能な限り大きくなろうとするもの。例えば、CenterListViewによって使われるボックス。
  • 自身のchildrenと同じ大きさになろうとするもの。例えば、TransformOpacityによって使われるボックス。
  • ある特定のサイズになろうとするもの。例えば、ImageTextによって使われるボックス。

例えば、ContainerのようないくつかのWidgetsは、コンストラクタの引数に基づいてタイプが異なります。
Containerの場合、デフォルトではできるだけ大きくなろうとしますが、例えばwidthを与えた場合、それを優先して特定のサイズになろうとします。

例えば、RowColumn(flex boxes)といった他のwidgetは、Flexセクションで後述するように、受け取った制約に基づいて変化します。

制約は「厳しく」なる場合があります。つまり、レンダーボックスがサイズを決める余地がなくなります(例えば、最小と最大の幅が同じ場合、厳しい幅を持つと言います)。
この例は、RenderViewclassに含まれているAppwidgetです。
アプリケーションのbuild関数によって返されたchildが使用するボックスには、アプリケーションのコンテンツ領域を正確に埋めるように(たいていはスクリーン全体)強制する制約が与えられます。
Flutterのボックスの多く、特に1つのchildしか持たないボックスは、自身の制約をchildrenに渡します。
つまり、アプリケーションのレンダーツリーのRootで、たくさんのボックスを入れ子にした場合、これらは厳しい制約によって強制され、互いにフィットします。

一部のボックスは制約を緩和します。つまり、最大値は維持されますが、最小値は削除されます。
例えば、Centerです。

補足

MaterialApphomeに直接Containerを使ってwidth, heightを指定しても、適用されない。

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
      home: Container(
        width: 50,
        height: 50,
        color: Colors.cyan  
      ),
    )
  );
}

image.png

Centerなどでラップすると、制約が緩められ、Containerに指定した制約が適用されるようになる。

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
      home: Center(
        child: Container(
          width: 50,
          height: 50,
          color: Colors.cyan  
        ),
      )
    )
  );
}

image.png

Unbounded constraints

ある状況では、ボックスに与えられた制約は、「無制限」あるいは無限になります。
つまり、最大の幅または最大の高さにdouble.INFINITYがセットされるということです。

無制限の制約が指定されている場合、できるだけ大きくなろうとするボックスは有効に機能せず、
デバッグモードでは、そのような組み合わせはそのファイルを指す例外を投げます。

レンダーボックスが無制限の制約を持っているとわかる最も一般的なケースは、flex boxes(RowColumn)の中や、スクロール可能な領域(ListViewや他のScrollViewsubclasses)内にあります。

特に、ListViewは、利用可能なスペースを埋めようと、そのcross-directionに広がろうとします。(例えば、垂直方向のスクロールブロックの場合、親と同じ幅になろうとします。)
垂直スクロールのListViewを水平スクロールのListViewにネストする場合、中のものはできるだけ広くなり、外のものはその方向にスクロールできるため、無限に広くなります。

Flex

Flex boxes(RowColumn)自体の動作は、それらが指定された方向に境界のある制約なのか無制限の制約なのかによって異なります。

境界がある制約の場合、その方向にできるだけ大きくなろうとします。

境界がない制約の場合、childrenをその方向にフィットさせようとします。
この場合childrenのflexを0(デフォルト値)以外に設定することはできません。
Widget Libraryでは、これは、Flex boxが他のFlex boxまたはスクロール可能なオブジェクト内にある場合、Expandedを使用できないことを意味します。
そうすると、このドキュメント示す例外メッセージが表示されます。

cross-direction、例えば、Column(垂直のflex)の幅やRow(水平のflex)の高さでは、決して境界なしにしてはいけません。
そうでなければ、それらはchildrenを合理的に整列させることができません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0