Flutter レイアウト基礎
レイアウトは Flutter UI 開発の中核となる概念です。
このセクションでは、Row、Column、Stack、Flex など、最もよく使われるレイアウト Widget を紹介します。
レイアウト Widget の概要
Flutter は豊富なレイアウト Widget を提供しており、さまざまな UI デザインのニーズに対応できます。
| Widget | 用途 |
|---|---|
| Row | 子 Widget を水平に配置する |
| Column | 子 Widget を垂直に配置する |
| Stack | 子 Widget を重ねて配置する |
| Flex | 柔軟な線形レイアウト(Row/Column の基底クラス) |
| GridView | グリッドレイアウト |
| ListView | リストレイアウト |
Row - 水平レイアウト
Row は子 Widget を水平方向に配置するために使います。
例:Row の基本的な使い方
// 3つのアイコンを水平に配置
Row(
children: [
Icon(Icons.home, color: Colors.blue),
Icon(Icons.search, color: Colors.green),
Icon(Icons.settings, color: Colors.grey),
],
)
// 間隔付きの Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 主軸の整列方法
children: [
Icon(Icons.home, color: Colors.blue),
Icon(Icons.search, color: Colors.green),
Icon(Icons.settings, color: Colors.grey),
],
)
Row(
children: [
Icon(Icons.home, color: Colors.blue),
Icon(Icons.search, color: Colors.green),
Icon(Icons.settings, color: Colors.grey),
],
)
// 間隔付きの Row
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 主軸の整列方法
children: [
Icon(Icons.home, color: Colors.blue),
Icon(Icons.search, color: Colors.green),
Icon(Icons.settings, color: Colors.grey),
],
)
mainAxisAlignment - 主軸の整列
| 值 | 説明 |
|---|---|
| MainAxisAlignment.start | 左揃え(デフォルト) |
| MainAxisAlignment.center | 中央揃え |
| MainAxisAlignment.end | 右揃え |
| MainAxisAlignment.spaceBetween | 両端揃え、アイテム間の間隔は等しい |
| MainAxisAlignment.spaceEvenly | アイテム間と両端の間隔が等しい |
| MainAxisAlignment.spaceAround | アイテム間の間隔は等しく、両端の間隔より大きい |
Column - 垂直レイアウト
Column は子 Widget を垂直方向に配置するために使います。
例:Column の基本的な使い方
// 3つのテキストを垂直に配置
Column(
children: [
Text('1行目', style: TextStyle(fontSize: 20)),
Text('2行目', style: TextStyle(fontSize: 20)),
Text('3行目', style: TextStyle(fontSize: 20)),
],
)
// 間隔と整列を設定した Column
Column(
mainAxisAlignment: MainAxisAlignment.center, // 垂直方向の中央揃え
crossAxisAlignment: CrossAxisAlignment.start, // 水平方向の左揃え
children: [
Text('タイトル', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 8),
Text('内容内容内容'),
const SizedBox(height: 8),
Text('下部の説明'),
],
)
Column(
children: [
Text('1行目', style: TextStyle(fontSize: 20)),
Text('2行目', style: TextStyle(fontSize: 20)),
Text('3行目', style: TextStyle(fontSize: 20)),
],
)
// 間隔と整列を設定した Column
Column(
mainAxisAlignment: MainAxisAlignment.center, // 垂直方向の中央揃え
crossAxisAlignment: CrossAxisAlignment.start, // 水平方向の左揃え
children: [
Text('タイトル', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 8),
Text('内容内容内容'),
const SizedBox(height: 8),
Text('下部の説明'),
],
)
crossAxisAlignment - 交差軸の整列
| 值 | 説明 |
|---|---|
| CrossAxisAlignment.start | 上揃え/左揃え |
| CrossAxisAlignment.center | 中央揃え |
| CrossAxisAlignment.end | 下揃え/右揃え |
| CrossAxisAlignment.stretch | 引き伸ばして親コンテナを満たす |
Expanded と Flexible
Expanded と Flexible は、子 Widget に残りのスペースを埋めさせるために使います。
例:Expanded の使い方
// 固定幅 + 可変幅
Row(
children: [
// 固定幅 100
Container(width: 100, height: 50, color: Colors.red),
// 残りのスペースを占有
Expanded(
child: Container(height: 50, color: Colors.green),
),
// 固定幅 50
Container(width: 50, height: 50, color: Colors.blue),
],
)
// 比率を割り当て
Row(
children: [
// 1 の割合
Expanded(
flex: 1,
child: Container(height: 50, color: Colors.red),
),
// 2 の割合
Expanded(
flex: 2,
child: Container(height: 50, color: Colors.green),
),
// 1 の割合
Expanded(
flex: 1,
child: Container(height: 50, color: Colors.blue),
),
],
)
Row(
children: [
// 固定幅 100
Container(width: 100, height: 50, color: Colors.red),
// 残りのスペースを占有
Expanded(
child: Container(height: 50, color: Colors.green),
),
// 固定幅 50
Container(width: 50, height: 50, color: Colors.blue),
],
)
// 比率を割り当て
Row(
children: [
// 1 の割合
Expanded(
flex: 1,
child: Container(height: 50, color: Colors.red),
),
// 2 の割合
Expanded(
flex: 2,
child: Container(height: 50, color: Colors.green),
),
// 1 の割合
Expanded(
flex: 1,
child: Container(height: 50, color: Colors.blue),
),
],
)
Stack - 重ね合わせレイアウト
Stack は子 Widget を重ね合わせるために使います。浮動要素やレイヤー合成などの効果を実現するためによく使われます。
例:Stack の使い方
// 基本的な Stack
Stack(
children: [
// 最下層:背景画像
Container(
width: 200,
height: 200,
color: Colors.blue,
),
// 中間層:半透明のオーバーレイ
Container(
width: 180,
height: 180,
color: Colors.white.withOpacity(0.5),
),
// 最上層:テキスト
const Center(
child: Text(
'重ね合わせコンテンツ',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
],
)
// 位置指定付きの Stack
Stack(
children: [
Container(color: Colors.grey[300]),
// 右上に配置
Positioned(
right: 10,
top: 10,
child: Icon(Icons.close, color: Colors.red),
),
// 左下に配置
Positioned(
left: 10,
bottom: 10,
child: Text('左下のテキスト'),
),
],
)
Stack(
children: [
// 最下層:背景画像
Container(
width: 200,
height: 200,
color: Colors.blue,
),
// 中間層:半透明のオーバーレイ
Container(
width: 180,
height: 180,
color: Colors.white.withOpacity(0.5),
),
// 最上層:テキスト
const Center(
child: Text(
'重ね合わせコンテンツ',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
],
)
// 位置指定付きの Stack
Stack(
children: [
Container(color: Colors.grey[300]),
// 右上に配置
Positioned(
right: 10,
top: 10,
child: Icon(Icons.close, color: Colors.red),
),
// 左下に配置
Positioned(
left: 10,
bottom: 10,
child: Text('左下のテキスト'),
),
],
)
Padding と Margin
Padding と Margin を使って、要素の内側の余白と外側の余白を制御します。
例:Padding と Margin
// Padding を使って内側の余白を設定
Padding(
padding: const EdgeInsets.all(16.0), // 四方すべて16ピクセル
child: Text('内側の余白があるテキスト'),
)
// 各辺を個別に設定
Padding(
padding: EdgeInsets.only(
left: 10,
right: 20,
top: 5,
bottom: 5,
),
child: Text('カスタム内側の余白'),
)
// EdgeInsets.symmetric で対称な余白を設定
Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text('水平16、垂直8'),
)
// Container で margin と padding を組み合わせる
Container(
margin: const EdgeInsets.all(10), // 外側の余白
padding: const EdgeInsets.all(16), // 内側の余白
decoration: BoxDecoration(
color: Colors.blue[100],
borderRadius: BorderRadius.circular(8),
),
child: Text('コンテナの内容'),
)
Padding(
padding: const EdgeInsets.all(16.0), // 四方すべて16ピクセル
child: Text('内側の余白があるテキスト'),
)
// 各辺を個別に設定
Padding(
padding: EdgeInsets.only(
left: 10,
right: 20,
top: 5,
bottom: 5,
),
child: Text('カスタム内側の余白'),
)
// EdgeInsets.symmetric で対称な余白を設定
Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text('水平16、垂直8'),
)
// Container で margin と padding を組み合わせる
Container(
margin: const EdgeInsets.all(10), // 外側の余白
padding: const EdgeInsets.all(16), // 内側の余白
decoration: BoxDecoration(
color: Colors.blue[100],
borderRadius: BorderRadius.circular(8),
),
child: Text('コンテナの内容'),
)
Scaffold と AppBar
Scaffold は Material Design の基本的なページ構造を提供し、AppBar は上部のアプリケーションバーです。
例:Scaffold の基本構造
// Material Design のページ用スキャフォールド
Scaffold(
// 上部のアプリケーションバー
appBar: AppBar(
title: const Text('マイアプリ'),
backgroundColor: Colors.blue,
elevation: 4, // 影の深さ
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {},
),
],
),
// ページのメインコンテンツ
body: const Center(
child: Text('ページのメインコンテンツ'),
),
// フローティングアクションボタン
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
// 下部のナビゲーションバー
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'ホーム'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: '検索'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'マイページ'),
],
),
)
Scaffold(
// 上部のアプリケーションバー
appBar: AppBar(
title: const Text('マイアプリ'),
backgroundColor: Colors.blue,
elevation: 4, // 影の深さ
actions: [
IconButton(
icon: const Icon(Icons.search),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {},
),
],
),
// ページのメインコンテンツ
body: const Center(
child: Text('ページのメインコンテンツ'),
),
// フローティングアクションボタン
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
// 下部のナビゲーションバー
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: 'ホーム'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: '検索'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: 'マイページ'),
],
),
)