【Flutter/Dart】Scaffoldの使い方!アプリバーやドロワーの実装方法

【Flutter/Dart】Scaffoldの使い方!アプリバーやドロワーの実装方法

この記事からわかること

  • Flutter/DartScaffoldとは?
  • AndroidライクUI実装方法
  • アプリバードロワーの実装方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

公式リファレンス:Scaffold

Scaffold

FlutterのScaffoldアプリの基本的なレイアウト構造を、Material Designをベースにして構築するための土台となるWidgetです。Material DesignベースなのでAndroidライクなUIを簡単に実装できるようになります。

Scaffoldではアプリバー(上部バー)やドロワー(スライドメニュー)、フローティングボタン、ボトムバーなどをMaterial Designを使用して簡単に実装することが可能になります。Scaffoldは「足場」という意味なので、意味をわかっていれば想像しやすいかもしれません。

定義を確認してみると色々なプロパティが存在することがわかります。今回はこの中でもよく使うappBarbodyfloatingActionButtonなどの使い方を解説していきます。


class Scaffold extends StatefulWidget {

  const Scaffold({
    super.key,
    this.appBar,
    this.body,
    this.floatingActionButton,
    this.floatingActionButtonLocation,
    this.floatingActionButtonAnimator,
    this.persistentFooterButtons,
    this.persistentFooterAlignment = AlignmentDirectional.centerEnd,
    this.drawer,
    this.onDrawerChanged,
    this.endDrawer,
    this.onEndDrawerChanged,
    this.bottomNavigationBar,
    this.bottomSheet,
    this.backgroundColor,
    this.resizeToAvoidBottomInset,
    this.primary = true,
    this.drawerDragStartBehavior = DragStartBehavior.start,
    this.extendBody = false,
    this.extendBodyBehindAppBar = false,
    this.drawerScrimColor,
    this.drawerEdgeDragWidth,
    this.drawerEnableOpenDragGesture = true,
    this.endDrawerEnableOpenDragGesture = true,
    this.restorationId,
  });
}

iOSライクなUI(クパチーノデザイン)での実装をしたい場合はCupertinoPageScaffold Widgetを使用してください。

Scaffoldの使い方

Scaffoldは土台部分を構成するWidgetなので画面単位の土台として活用します。デフォルトのサンプルコードであるMyHomePage(StatefulWidgetなので実装は_MyHomePageState)にも実際に使われています。それぞれの部分を切り出しながら実装を確認していきます。


class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), 
    );
  }
}
Flutterとは?インストール〜開発環境構築までの手順!プロジェクト作成

appBar

コンストラクタの引数appBarアプリバー(上部バー)部分のUIを構築するWidgetを指定します。定義を確認すると指定できる型はPreferredSizeWidget?になっています。PreferredSizeWidget高さが明示的に指定されているという特徴があります。


/// Scaffoldの上部に表示されるappBar
final PreferredSizeWidget? appBar;

AppBarPreferredSizeWidgetを継承しているので基本的にAppBarを使用すればOKです。カスタムで実装したい場合はPreferredSizeWidgetを継承させる必要があります。

appBar: AppBar(
  // 背景色
  backgroundColor: Theme.of(context).colorScheme.inversePrimary,
  // アプリバーに表示したい文字列
  title: Text(widget.title),
),

アプリバーの右側にボタンを追加したい場合はactionsで指定します。この中に指定したWidgetがアプリバーの右側に配置されます。

AppBar(
  title: Text("登録"),
  actions: [
    IconButton(
      onPressed: () { add(context); }, 
      icon: Icon(Icons.check)
    ),
  ],  
)

body

コンストラクタの引数body画面に表示するメインコンテンツを指定します。Widget型で指定できるので任意のUIを指定することが可能ですが、指定したコンテンツはappBarやfloatingActionButton、drawerなどの下側に表示されるようになります。


/// Scaffoldの主なコンテンツ。
///
/// [appBar] の下、アンビエント [MediaQuery] の [MediaQueryData.viewInsets] の下部の上、および [floatingActionButton] と [drawer] の後ろに表示されます。[resizeToAvoidBottomInset] が false の場合、オンスクリーン キーボードが表示されても本体のサイズは変更されません。つまり、`viewInsets.bottom` によってインセットされません。
///
/// Scaffoldの本体のWidgetは、AppBarとScaffoldの下部の間の使用可能なスペースの左上に配置されます。代わりにこのWidgetを中央に配置するには、[Center] Widgetに配置し、それを本体にすることを検討してください。代わりにこのWidgetを展開するには、[SizedBox.expand] に配置することを検討してください。
///
/// 通常は画面に収まるWidgetの列があるが、オーバーフローする可能性があり、その場合はスクロールする必要がある場合は、Scaffoldの本体として [ListView] を使用することを検討してください。これは、本体がスクロール可能なリストである場合にも適しています。
final Widget? body;

例えばサンプルコードではCenterを使用して中央に配置し、Column要素を縦に並べ、その中にTextなどを配置しています。

body: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      const Text(
        'You have pushed the button this many times:',
      ),
      Text(
        '$_counter',
        style: Theme.of(context).textTheme.headlineMedium,
      ),
    ],
  ),
),

floatingActionButton

コンストラクタの引数floatingActionButton画面の右下に表示されるフローティングボタンを指定します。フローティングボタンはアプリでよくあるUIの1つです。


/// [body] の上の右下隅に浮かんで表示されるボタン。
///
/// 通常は [FloatingActionButton]。
final Widget? floatingActionButton;

例えばサンプルコードではFloatingActionButtonを使用しており、onPressedで実行したい処理を指定し、childでアイコンを指定しています。

floatingActionButton: FloatingActionButton(
  onPressed: _incrementCounter,
  tooltip: 'Increment',
  child: const Icon(Icons.add),
),

drawer

コンストラクタの引数drawer画面サイドからスライドして表示されるビューを指定します。Widget型で指定できるので任意のUIを指定することが可能です。


/// [body] の横に表示されるパネルで、モバイル デバイスでは非表示になっていることがよくあります。左から右 ([TextDirection.ltr]) または右から左 ([TextDirection.rtl]) にスワイプします。
///
/// 通常は [Drawer] です。
///
/// ドロワーを開くには、[ScaffoldState.openDrawer] 関数を使用します。
///
/// ドロワーを閉じるには、[ScaffoldState.closeDrawer]、[Navigator.pop]
/// のいずれかを使用するか、キーボードの Esc キーを押します。
///
/// {@tool dartpad}
/// モバイルでドロワーの端のスワイプを無効にするには、[Scaffold.drawerEnableOpenDragGesture] を false に設定します。次に、[ScaffoldState.openDrawer] を使用してドロワーを開き、[Navigator.pop] を使用して閉じます。
///
/// ** examples/api/lib/material/scaffold/scaffold.drawer.0.dart のコードをご覧ください **
/// {@end-tool}
final Widget? drawer;

DrawerWidgetを使用することで簡単にUIを実装することが可能です。AppBarには自動でドロワー表示用のハンバーガーアイコンが表示され、開閉のスライドアニメーションもよしなに実装してくれます。

'【Flutter/Dart】Scaffoldの使い方!アプリバーやドロワーの実装方法
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text("ドロワーの例")),
        drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: [
              const DrawerHeader(
                decoration: BoxDecoration(color: Colors.blue),
                child: Text(
                  "メニュー",
                  style: TextStyle(color: Colors.white, fontSize: 24),
                ),
              ),
              ListTile(
                leading: const Icon(Icons.home),
                title: const Text("ホーム"),
                onTap: () {
                  print("ホームが選択されました");
                },
              ),
              ListTile(
                leading: const Icon(Icons.settings),
                title: const Text("設定"),
                onTap: () {
                  print("設定が選択されました");
                },
              ),
            ],
          ),
        ),
        body: const Center(child: Text("メイン画面")),
      ),
    );
  }
}

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index