Scaffoldは、AppBar、Drawer、BottomNavigationBar、FloatingActionButtonを備えた基本的なMaterial Design画面構造を実装する、Flutterの中心的なウィジェットフレームワークです。要素を配置するだけでなく、正しいz順序とユーザージェスチャー処理を備えた既成のアーキテクチャを提供します。Flutterドキュメント(2026)によると、ScaffoldはSnackBarやBottomSheetを含むMaterialコンポーネントの正しい動作に必須のルート要素です。ContainerやColumnとは異なり、ScaffoldはSafeArea、アダプティブ背景、キーボード動作を自動的に管理し、モバイルアプリケーションの画面構築の標準となっています。
重要ポイント
ScaffoldはMaterial Designライブラリのレイアウトウィジェットで、画面の基本的な視覚構造を形成します。これは標準的なMaterialアプリケーションパターン(トップバー、画面本体、サイドメニュー、フローティングボタン)を実装します。単に寸法とスタイルを設定するContainerとは異なり、Scaffoldは画面全体を統合システムとして管理します。
Material Designで構築されたすべてのFlutterアプリケーションはMaterialAppで始まり、その中で各画面はScaffoldでラップされます。Scaffoldこそが、iPhone X以降のSafeAreaを考慮して、すべてのデバイスでAppBarの正しい表示を保証します。また、z順序にも責任を持ちます。Drawerはbodyの上に表示され、SnackBarはインターフェース全体の上に、しかしダイアログウィンドウの下に表示されます。
公式のFlutter APIリファレンス(2026)によると、ScaffoldはSnackBar、BottomSheet、PersistentBottomSheetなどのウィジェットの正しい動作に必須の要件です。Scaffoldがない場合、これらのコンポーネントはScaffoldコンテキストにアクセスするためにInheritedWidget Scaffold.ofに依存しているため、例外をスローします。したがって、Scaffoldの代わりに直接Containerにコンテンツを配置することは、初心者開発者によくある間違いであり、Material機能の喪失につながります。
典型的なFlutterアプリケーションでは、ScaffoldはMaterialApp内に位置し、通常はクロスプラットフォーム開発においてWidgetsAppまたはCupertinoAppの下に配置されます。MaterialAppはNavigatorとテーマを作成し、Scaffoldは現在の画面の構造を定義します。各画面は独自のAppBar、Drawer、BottomNavigationBarを持つ独自のScaffoldを持つことができ、特定のページに合わせてインターフェースを柔軟にカスタマイズできます。
高度なカスタマイズのために、ScaffoldをNestedScrollViewと組み合わせることができます。これにより、パララックス効果のある折りたたみ可能なAppBarなどの複雑なスクロール効果を実装できます。ただし、ほとんどの場合、標準のScaffoldとそのプロパティでプロダクション対応の画面を構築するのに十分です。
Scaffoldは、いくつかの必須およびオプションのゾーンで構成され、それぞれがインターフェースの特定の部分を担当します。各部分を個別に見て、それらがどのように相互作用するかを理解しましょう。
AppBarは、タイトル、ナビゲーションボタン、アクションを表示する画面の上部バーです。自動的に正しい高さ56dpを取得し、ノッチ付きデバイスのSafeAreaを考慮します。bottomプロパティを使用して、タブ切り替え用のTabBarをAppBarに埋め込むことができます。
Drawerは左からスライドアウトするパネルで、アプリケーションのセクション間のナビゲーションを提供します。drawerプロパティが設定されている場合、Scaffoldは自動的にAppBarにハンバーガーアイコンを追加します。DrawerにはDrawerHeader、メニュー項目のListView、ユーザー情報を含めることができます。
BottomNavigationBarは、メインセクションを切り替えるための画面下部のパネルです。ラベル付きの2〜5個のアイコンを含み、NavigationBarを介したアクティブ表示でMaterial 3をサポートします。Scaffoldはこれを画面下部に配置し、コンテンツが重ならないように自動的にbodyを上にシフトします。
FloatingActionButtonは画面の右下隅に配置される丸いボタンです。新しいエントリの追加やメッセージの送信など、画面上のメインアクションに使用されます。Scaffoldはextendedプロパティを通じて拡張アニメーションを持つ複数のFABをサポートします。
Bodyはメインコンテンツが配置される画面の中央領域です。bodyとして任意のウィジェット(Column、ListView、GridView、Stack、カスタム構成)を使用できます。ScaffoldはAppBar、BottomNavigationBar、SafeAreaを考慮してbodyの高さを自動的に計算し、手動でのサイズ調整を不要にします。
Scaffoldは、画面の外観と動作をカスタマイズするための30を超えるプロパティを提供します。これらには、必須のもの(body)と、マージン、背景、キーボード状態を制御するオプションのものがあります。各プロパティを理解することで、デザイン要件に応じてインターフェースを正確に構成できます。
| プロパティ | 型 | 説明 |
|---|---|---|
| appBar | PreferredSizeWidget? | タイトルとアクションを備えた画面の上部バー |
| body | Widget? | AppBarとBottomNavigationBarの間の画面のメインコンテンツ |
| drawer | Widget? | 左からのスワイプで開くサイドパネル |
| bottomNavigationBar | Widget? | ボトムナビゲーションバー(BottomNavigationBarまたはNavigationBar) |
| floatingActionButton | Widget? | フローティングアクションボタン |
| backgroundColor | Color? | テーマを上書きするScaffoldの背景色 |
| resizeToAvoidBottomInset | bool | キーボード表示時のbodyの自動圧縮 |
resizeToAvoidBottomInsetプロパティはフォームを扱う際に特に重要です。true(デフォルト)に設定されている場合、キーボードが表示されるとScaffoldは自動的にbodyを圧縮し、入力フィールドを表示したままにします。これにより、カスタムキーボードリスナーを記述する必要がなくなります。SingleChildScrollViewを使用するカスタムシナリオでは、このプロパティを無効にできます。
Materialコンポーネントの完全なセットを備えたScaffoldの実践的な例を見てみましょう。このコードは、AppBar、Drawer、BottomNavigationBar、FloatingActionButton、SnackBarを備えた画面を作成します。これはFlutterの典型的なモバイルアプリケーション構造です。
class MainScreen extends StatefulWidget {
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int selectedIndex = 0;
final List<Widget> pages = [
const HomePage(),
const SearchPage(),
const ProfilePage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('マイアプリ'),
actions: [
IconButton(icon: const Icon(Icons.search), onPressed: () {}),
],
),
body: pages[selectedIndex],
drawer: Drawer(
child: ListView(
children: [
const DrawerHeader(child: Text('メニュー')),
ListTile(title: const Text('設定'), onTap: () {}),
],
),
),
bottomNavigationBar: NavigationBar(
selectedIndex: selectedIndex,
onDestinationSelected: (int index) {
setState(() => selectedIndex = index);
},
destinations: const [
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
NavigationDestination(icon: Icon(Icons.search), label: 'Search'),
NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('アクション完了')),
);
},
child: const Icon(Icons.add),
),
);
}
}
この例では、廃止予定のBottomNavigationBarの代わりにMaterial 3のNavigationBarを使用しています。Scaffoldはすべてのパーツを自動的にリンクします。Drawerを開くとSnackBarは非表示になり、タブを切り替えるとbodyが更新され、FloatingActionButtonはそのまま残ります。ScaffoldMessengerは、階層内に複数のScaffoldがある場合でもSnackBarの表示を保証します。
Material 3(M3)は、Googleが2023年に発表したMaterial Designの進化版です。M3のScaffoldにはいくつかの変更が加えられました。BottomNavigationBarの代わりに新しいNavigationBarウィジェット、ColorScheme.fromSeedによるダイナミックカラーのサポート、マージンとコンポーネントの高さに関する更新された推奨事項です。M3への移行にScaffoldの交換は必要ありません。アプリケーションのテーマを更新するだけです。
プロジェクトでMaterial 3を有効にするには、ThemeDataでuseMaterial3: trueを設定する必要があります。Scaffoldは自動的にビジュアルスタイルを適応させます。マージンが大きくなり(16dpから24dp)、色がシードカラーから再計算され、FloatingActionButtonのサイズが大きくなり角が丸くなります。同時に、既存のすべてのScaffoldプロパティは機能し続けます。
Material Design 3仕様(2026)によると、BottomNavigationBarの代わりに3〜5項目のNavigationBarを使用することを推奨しています。Scaffoldは両方のオプションをサポートしていますが、NavigationBarはPixelデバイスでの適応性とMaterial Youのサポートに優れています。
M3でScaffoldを正しく動作させるには、テーマを更新してBottomNavigationBarをNavigationBarに置き換えるだけで十分です。色はColorScheme.fromSeedを介して自動的に計算され、Scaffoldはマージンを新しい標準に調整します。必要に応じて、backgroundColorを直接上書きできます。
よくある質問
ScaffoldはMaterialコンポーネント(AppBar、Drawer、SnackBar)をサポートする画面全体のウィジェットフレームワークであり、Containerは画面構造管理なしの単一の子要素用の基本コンテナです。Scaffoldはz順序、SafeArea、自動ジェスチャー処理を提供し、Containerは寸法とスタイルのみを設定します。
技術的には可能ですが、実際には推奨されません。Scaffoldを別のScaffoldの中にネストすると、内側のScaffoldが独自のAppBarとBottomNavigationBarを作成し、パネルの重複とz順序の混乱を引き起こします。複雑なレイアウトの場合は、単一のScaffoldのbody内でNestedScrollViewまたはColumnを使用してください。
SnackBarはScaffoldの子コンポーネントであり、正しく表示するにはウィジェットツリー内にScaffoldが必要です。ScaffoldはScaffoldStateを提供し、それを通じてSnackBarが表示をアニメーション化し、画面下部に配置されます。Scaffoldがない場合、SnackBarはInheritedWidgetを介してコンテキスト内でScaffoldStateを見つけられないため、例外をスローします。
Scaffoldの背景色はbackgroundColorプロパティで設定され、特定の画面のテーマカラーを上書きします。背景をグローバルに変更する必要がある場合は、ThemeDataでscaffoldBackgroundColorを設定します。Material 3はColorScheme.surfaceから背景色を自動的に計算しますが、手動で上書きできます。
ScaffoldMessengerはFlutter 2.5で導入されたユーティリティで、階層内の現在のScaffoldとは独立してSnackBarとBottomSheetを表示できます。廃止予定のScaffold.of(context)とは異なり、ScaffoldMessengerは画面間のナビゲーション時に正しく動作し、アニメーション中にコンテキストを失いません。ユーザーフィードバックには常にScaffoldMessengerを使用することをお勧めします。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。