🤔
FlutterでRowの中にTextFieldを入れると表示されない場合の対処法
はじめに
Flutterで以下のようにテキストフィールドとテキストを横並びにするレイアウトを作りたい時がありました。
ただシンプルに次のように書くとなぜかテキストフィールドが表示されない問題があったので、
この修正方法についてまとめておきます。
Row(
children: <Widget>[
TextField(decoration: InputDecoration(labelText: '未入力')),
Text(
'cm',
style: TextStyle(fontSize: 18),
)
],
),
発生した現象
以下のようにテキストフィールドも横のテキストも表示されなくなります。
DEBUG CONSOLEを確認すると、次のようなエラーが出てしまっているようです。
RenderBox was not laid out: RenderTransform#d58d5 NEEDS-LAYOUT NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1940 pos 12: 'hasSize'
結論
以下のようにFlexibleウィジェットでTextFieldを囲んであげると直ります。
Row(
children: <Widget>[
Flexible(
child: TextField(
decoration: InputDecoration(labelText: '未入力'))),
Text(
'cm',
style: TextStyle(fontSize: 18),
)
],
),
原因
Rowは子のウィジェットに必要なスペースを認識する必要があります。
widthを明示的に指定していない場合は内容のサイズで認識することができますが、
TextFieldはテキスト内容も持っていません。
そのため、Rowがスペースの確保に必要なサイズを認識できずエラーとなってしまいます。
代替案① 明示的にwidthを指定する
ContainerでTextFieldを囲み、明示的にwidthを指定しても直ります。
Row(
children: <Widget>[
Container(
width: 340,
child: TextField(
decoration: InputDecoration(labelText: '未入力'))),
Text(
'cm',
style: TextStyle(fontSize: 18),
)
],
),
代替案② ExpandedでTextFieldを囲む
Flexibleの代わりにExpandedを使っても同様の結果が得られます。
Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(labelText: '未入力'))),
Text(
'cm',
style: TextStyle(fontSize: 18),
)
],
),
FlexibleとExpandedの違いについてはこちらの記事が分かりやすいです。
どちらも囲んだ要素を画面一杯に広げ、比率を指定して各要素の幅を調整できるウィジェットです。
Flexibleは子のサイズに応じた比率で表示されるのですが、
TextFieldはテキスト内容を持たないため、Expandedと同様に画面一杯に広がります。
さいごに
今回の調査でFlexibleとExpandedの使い方について理解を深めることができました。
RowとColumnはFlutterでレイアウトを作る時に必ずと言っていいほど利用するので、
上手くこれらのウィジェットを組み合わせていきたいですね。
参考にした記事
Discussion