FlutterでRowウィジェットをわかりやすく解説
はじめに
Flutterを使っていると、画面の構成要素を横方向に並べたい場面が多いのではないでしょうか。 そんなときに便利なのが、Row ウィジェットです。
しかし、初めてFlutterを触るときには、どう使えばいいのかピンとこないこともあるかもしれません。 縦方向に配置するColumnとはどう違うのか、レイアウト上のプロパティはどう考えるとわかりやすいのか、疑問に思う方もいるでしょう。
この記事では、Rowを使った具体的なコード例や、実務での利用シーンをもとにわかりやすく説明します。 余計な専門用語をできるだけ省きつつ、初心者でも読めば理解できるような流れを心がけています。
この記事を読むとわかること
- Rowウィジェットの基本的な役割
- 縦方向のレイアウトとの違いと実務での使い分け
- プロパティを組み合わせた配置方法と、その考え方
- Rowの活用事例や気をつけたいポイント
- レイアウト崩れを防ぐための実践的なテクニック
Rowウィジェットの概要
Rowは、子ウィジェットを横一列に並べるための仕組みを提供します。 たとえば、ボタンとテキストを横並びにしたいときや、アイコンを数個並べてメニューバーを作りたいときなどに役立ちます。
Flutterのレイアウトは、基本的にウィジェットを組み合わせて作るスタイルです。 Rowはそうしたウィジェットの中でも最もよく使うものの一つであり、画面の大枠を決める重要な存在といえます。
一方で、要素数が多くなりすぎたり、画面幅より大きな要素を無理に詰め込みすぎたりすると、画面外に要素が溢れてしまうことがあります。 そのため、Rowの挙動やプロパティをちゃんと押さえておくと、実務でも混乱しにくくなるでしょう。
Rowが担う役割
Rowは、 主軸 (horizontal axis) に沿ってウィジェットを配置するものです。 Flutterでは、縦方向のレイアウトはColumnが担い、横方向のレイアウトはRowが担います。
もし横方向に並べるだけでは不十分で、折り返しもしたい場合にはWrapなどを検討する必要があります。 Rowはあくまで一行で収まるケースに向いているため、要素が増えればOverflowエラーや見切れが発生することもあります。
Columnとの違い
Rowが横配置なのに対し、Columnは縦配置のウィジェットです。 どちらも子ウィジェットをリストのように並べる点は共通していますが、子ウィジェットの並ぶ方向が異なるだけで、使い方が大きく変わってきます。
実務では、RowとColumnを組み合わせて、より複雑な画面レイアウトを作ることが一般的です。 まずはRow単体の特徴をしっかり理解し、Columnとの違いや使い分けを押さえておくと、後々のレイアウト設計がスムーズになるのではないでしょうか。
Rowウィジェットの基本プロパティ
Rowにはいくつかのプロパティがあります。 特に重要なのは、mainAxisAlignment や crossAxisAlignment といった、要素をどのように配置するかを決めるプロパティです。
mainAxisAlignment
Rowの場合、mainAxisAlignment は横方向の配置を決定します。 要素を左寄せにする、中央揃えにする、均等配置にするなど、さまざまな並べ方が選べます。
代表的な値として以下のようなものがあります。
- MainAxisAlignment.start:先頭に寄せる
- MainAxisAlignment.center:中央に配置する
- MainAxisAlignment.end:末尾に寄せる
- MainAxisAlignment.spaceBetween:ウィジェット間を均等に開けて配置する
- MainAxisAlignment.spaceAround:ウィジェット間を均等に開け、両端にも余白を作る
- MainAxisAlignment.spaceEvenly:全ての隙間が等しいスペースになる
Rowの画面幅を想定しながら、どのように要素を並べるかを決めるとよいでしょう。
crossAxisAlignment
これは縦方向(Rowの場合は副軸)への配置方法を決めるプロパティです。
- CrossAxisAlignment.start:上側に寄せる
- CrossAxisAlignment.center:中央寄せ
- CrossAxisAlignment.end:下側に寄せる
- CrossAxisAlignment.stretch:縦方向に引き伸ばす
Rowの高さは子ウィジェットの中で最も高さがあるものに合わせられます。 もしRow全体をぎりぎりまで縦に拡大したい場合は、CrossAxisAlignment.stretchを使うと便利です。
mainAxisSize
mainAxisSize は主軸方向のサイズをどのように決定するかを設定します。
- MainAxisSize.max:可能な限り広げる
- MainAxisSize.min:必要最小限のサイズに留める
通常はmainAxisSize: MainAxisSize.maxがデフォルトですが、要件に応じて設定を変更すると、意図しない余白を減らすことができます。
Rowの実践例
実際に、Rowを使った簡単なコード例を見てみましょう。 アイコンとテキストを横一列に並べ、中央に寄せたいケースを想定します。
import 'package:flutter/material.dart'; class ExampleRowScreen extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Row Example'), ), body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Icon(Icons.favorite, color: Colors.red), SizedBox(width: 8), Text('Favorites'), ], ), ), ); } }
上のコードでは、RowのなかにIconとTextを並べており、SizedBoxを使ってアイコンとテキストの間に余白を取っています。 mainAxisAlignmentとcrossAxisAlignmentをcenterにしてあるので、画面中央にまとまる見た目になります。
実務では、アイコンとテキストを一緒にレイアウトしたい場面は多々あります。 例えばボタンラベルを分かりやすくするために、アイコンと文字を組み合わせるというのはよくある手法です。
使い方のコツと注意点
Rowを使う上で、実務ならではのコツがあります。 単に横一列に並べるだけでなく、要素数や画面サイズを意識することが大切です。
Overflowのリスク
Row内の子ウィジェットが多かったり、幅の大きいウィジェットを含んでいたりすると、画面外にはみ出してエラーになることがあります。 特に小さいデバイスでテキスト量が多い場合など、意図せずに文字が見切れることもあるでしょう。
ここでは、解決策として以下のような方法が考えられます。
- Expanded や Flexible を使って要素に柔軟な余白を与える
- Wrap ウィジェットを使って折り返す
Rowにこだわりすぎず、画面サイズに応じたレイアウトを考えることがポイントです。
ExpandedやFlexibleの活用
Rowの中にテキストやボタンを複数入れたいけれど、均等に画面幅を分割したい場合があります。 そのときに便利なのがExpandedやFlexibleです。
以下のコード例は、Row内で要素を均等に横幅を分割して配置するイメージです。
Row( children: [ Expanded( child: Container( color: Colors.blue, child: Text('Left'), ), ), Expanded( child: Container( color: Colors.green, child: Text('Right'), ), ), ], )
これにより、Rowが持つスペースを2つの要素で均等に分割し、それぞれのコンテナが幅を半分ずつ持つようになります。 ユーザーの画面サイズに合わせて伸縮するので、より柔軟なレイアウトが可能になります。
実務での活用シーン
Rowは、タブバーのようなナビゲーションを作ったり、ボタンを横に並べて操作パネルを作ったりするときにも使われます。 たとえば、ECサイトのような画面で「カートに追加する」「お気に入りに登録する」など、複数の操作をひとつの行にまとめたいときに利用すると見やすくなります。
また、RowとColumnを入れ子にして、横方向・縦方向を組み合わせることで、より複雑なUIを作ることが多いでしょう。 実務でのプロジェクトでは、画面全体を複数の段や列にわけ、そこに表示したいWidgetを配置していきます。 Rowはその基礎となる部分なので、しっかり理解しておくと後々の開発で迷いにくくなります。
レスポンシブデザインへの応用
最近は、多種多様なデバイスサイズに対応するアプリが求められています。 Rowを使ったシンプルな横並びレイアウトでも、デバイスの幅によってウィジェットが見切れる恐れがある場合はレイアウト切り替えが必要になるかもしれません。
その際、MediaQuery などを使って、画面幅に応じてレイアウトを分岐することも考えられます。 広い画面ならRowで並べ、狭い画面ならColumnに切り替えるといった実装を行うこともあります。
Rowのレイアウト崩れを防ぐポイント
Rowを使っていると、思わぬ箇所でレイアウトが崩れるケースがあります。 特に、テキストを多く含む場合は注意が必要です。
テキストの長さを想定した設計
海外向けや多言語対応を考えると、文字列が予想外に長くなってしまうことがあります。 Rowでは折り返しが基本的に行われず、子ウィジェットの幅がそのまま必要になるため、レイアウトが大きくズレることがあるでしょう。
もし可能であれば、WrapやFlexibleを組み合わせて、テキストがある程度折り返せるようにするか、表示スペースを確保するように設計する必要があります。
SizedBoxやSpacerでの余白調整
Rowでウィジェットを並べるとき、余白の扱いが曖昧だとデザインのバランスが崩れます。 適度にSizedBoxやSpacerを挟むことで、見やすい余白をコントロールできます。
SpacerはExpandedの亜種のような役割を果たし、Rowの余白を自動的に広げるイメージです。 手動でSizedBoxを配置して幅を指定するより、ダイナミックに調整できる場合もあります。
ColumnやWrapとの比較
Row以外にも、FlutterにはColumnやWrap、Stackなど多様なレイアウトウィジェットがあります。 ここでは、Rowとの使い分けのヒントをまとめます。
Columnとの使い分け
Columnは縦並びで、Rowは横並びという単純な違いです。 1列なのか1行なのかを明確にしたうえで、それぞれの特性を使いこなすとよいでしょう。
Wrapとの使い分け
要素が横幅に収まらない場合に折り返しを行う必要があるなら、Wrap ウィジェットが有効です。 Rowは折り返しがなく、Overflowが起きるとエラーになります。
Wrapを使うことで、画面幅に収まらなくなった要素を自動的に次の行に移動できます。 ただし、折り返しの制御はRowほど単純ではなく、ちょっとした調整に工夫が必要になることもあります。
Stackとの使い分け
Stackは、ウィジェットを重ねて配置したい場合に使われます。 横並びや縦並びではなく、前後方向に並べたいときにはStackを検討することがあるでしょう。
よくある疑問とトラブルシュート
初めてRowを使うときに躓きがちなポイントや、よく聞く疑問をピックアップしてみましょう。
mainAxisAlignmentとcrossAxisAlignmentを間違える
RowではmainAxisAlignmentが横方向に関わり、crossAxisAlignmentが縦方向です。 Columnの場合はこの逆になりますので、最初は混乱しがちです。
こうした間違いを防ぐためには、Rowは横、Columnは縦という基本イメージを常に意識しておくとよいでしょう。
アイテム同士のスペース調整に苦労する
Row内のアイテム間の余白が足りなかったり広すぎたりすると、見た目が不格好になります。 SizedBoxやSpacerを使いこなせば、配置が安定しやすくなるはずです。
個人的には、SizedBoxを使ってピンポイントで固定幅を空けるか、MainAxisAlignment.spaceBetweenやMainAxisAlignment.spaceEvenlyを選ぶ形がシンプルだと感じるケースが多いです。
Overflowエラーが出てしまう
Row内に収まりきらない要素を詰め込むと、エラーが出ます。 どうしても一行に収めたい場合はリデザインを検討するか、スクロール可能なSingleChildScrollViewを組み合わせる方法もあります。
レイアウトのテスト方法
Rowがうまく機能しているかどうかを確かめるときは、デバイスサイズを変えていろいろと確認するのが基本です。 エミュレータや実機で横画面や小さい画面、大きい画面などを試しながら、表示崩れや文字切れがないかチェックすることをおすすめします。
テストは手間がかかるイメージがあるかもしれませんが、実務で時間を節約するためにも大切です。 マージ前に複数のデバイス上で確認すると、リリース後のトラブルをぐっと減らせるでしょう。
Rowに関する補足知識
Flutterには、Rowの配置や余白設定をさらに細かく制御するためのウィジェットやプロパティが多数用意されています。 以下のようなものを見かけたら、Rowと組み合わせて使えるかもと意識してみると、新しいレイアウトのアイデアが広がります。
FlexibleとFractionallySizedBox
Row内で要素ごとに比率を変えたいとき、FractionallySizedBox を使って画面の何割を占めるか指定する方法もあります。 Flexibleと組み合わせれば、よりダイナミックなレイアウトが可能になるでしょう。
Alignment関連の小技
Rowウィジェットとは直接関係ありませんが、ContainerやAlignなど別のウィジェットで配置を調整することもあります。 Rowの中にさらにContainerを仕込んでAlignmentを変更するなど、レイアウトが複雑になるほど混乱しやすいので、どこで設定しているかを整理しておくとミスが減ります。
Rowのまとめレイアウト例
ここで、RowとColumnを組み合わせた簡単なレイアウト例を示します。 ボタンやテキストを横並び、縦並びに織り交ぜながらUIを構成するイメージです。
import 'package:flutter/material.dart'; class ComplexLayoutExample extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Complex Layout Example'), ), body: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ElevatedButton( onPressed: () {}, child: Text('Button 1'), ), ElevatedButton( onPressed: () {}, child: Text('Button 2'), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.settings, size: 32), SizedBox(width: 12), Text('Settings Panel'), ], ), ], ), ); } }
上記の例では、Columnで全体を縦に2分割し、それぞれのセクションをRowで横並びにしています。 このように組み合わせることで、複雑な画面レイアウトを比較的シンプルに構築できます。
Rowを使うときの最終的なポイント
Rowは、横方向のレイアウトを管理するうえで欠かせない存在です。 ただし、画面を見やすく整理するには、要素の数やサイズ、余白、折り返しの必要性などをトータルで考える必要があります。
Row一つで解決できない場合は、ColumnやWrapなどのウィジェットをうまく併用しながら、ユーザーにとってわかりやすいUIを目指すのがよいでしょう。
アイコンや文字が画面外にはみ出す場合は、Rowの限界を超えているサインです。 Wrapやスクロールを検討して、柔軟にレイアウトを変更しましょう。
まとめ
Rowウィジェットは、Flutterで横方向に並べたい要素をシンプルに配置できる便利なウィジェットです。 しかし実務では、単に横に並べるだけでは済まない場面も多く、Overflowやレイアウト崩れといった問題に直面することがあります。
そこで、mainAxisAlignment や crossAxisAlignment をしっかり把握し、必要に応じて SizedBox や Spacer、Expanded などを活用することで、柔軟なUIを作れるようにしておくことが大切です。 また、RowだけでなくColumn、Wrap、Stackなどのレイアウトウィジェットを組み合わせて使えば、より複雑な画面構成にも対応できるでしょう。
皆さんもまずはRowで簡単なUIを作ってみて、慣れてきたらColumnやWrapなどと組み合わせてレイアウトを工夫してみてはいかがでしょうか。 そうすることでFlutterによる画面開発の自由度がぐっと広がるはずです。