【Flutter】Drawer内のSwitchでフラグ操作をして、フラッグを表示/非表示するアプリの作り方

2021-07-07

はじめに

今回は画面の隅から中央に向けてスワイプすると出てくるメニューバーを実装します。 FlutterではDrawerという名前で準備されています。

Androidだと、Navigation Drawer等と呼ばれていた機能ですね。 xmlで画面レイアウトを作り、DrawerLayout として呼び出してDrawerToggleとして作る手間がかかる機能でした。

Flutterだとクソ簡単なので解説も何も無いですが…やっていきましょう。

今回は、フラグ操作してフラッグ(国旗)を表示したり消したりするアプリを作るところを目標にします。 歳を取るとイカンですね。こんな寒いギャグを…

実装

プロジェクトを作ります。

flutter create drawer

作成したプロジェクトでDrawerを追加したい画面のレイアウトで下記を追加します。

drawer: Drawer(child: Center(child: Text("なんか"))),

実際に書くとこのような形になります。

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'You have pushed the button this many times:',
          ),
          Text(
            '$_counter',
            style: Theme.of(context).textTheme.headline4,
          ),
        ],
      ),
    ),
+    drawer: Drawer(child: Center(child: Text("ひょっこりはん"))),
    floatingActionButton: FloatingActionButton(
      onPressed: _incrementCounter,
      tooltip: 'Increment',
      child: Icon(Icons.add),
    ), // This trailing comma makes auto-formatting nicer for build methods.
  );
}
}

実行結果

実行して、画面左からスワイプするとこのような画面になります。

右からも出したい場合

endDrawer: Drawer(child: Center(child: Text("右から")))

drawerの代わりにendDrawerを使うと右から出すこともできます。 当然併記すれば両方からだすこともできます。

Drawer内でFlagを立てるとフラッグを表示してみる。

画像を貼り付けても良いですが、各国の国旗を出力できるパッケージがあるのでそちらを使用します。

flag

flutter pub add flag

Flutter プロジェクトに追加します。

日本国の国旗を表示する場合このように書きます。

この2つをインポートしてFlag.fromCodeを呼び出します。

import 'package:flag/flag.dart';
import 'package:flutter/cupertino.dart';
Flag.fromCode(
              FlagsCode.JP,
              height: 300,
),

フラッグ表示の実装例

先程まで作ってきたアプリに国旗表示部分を追加します。

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'フラグを立てるとフラッグが出てくる',
          ),
+          Flag.fromCode(
+            FlagsCode.JP,
+            height: 300,
+          ),
        ],
      ),
    ),
    drawer: Drawer(child: Center(child: Text("ひょっこりはん"))),
    endDrawer: Drawer(child: Center(child: Text("右から"))),
  );
}
}

実行結果

日本国の国旗が表示されました。

 Switchを使ってフラグを建てたり落としたりします。

Flutter Doc JP Switch 説明記事はここがわかりやすいと思います。

endDrawerの中にSwitchを追加してみましょう。

Class内にSwitchの状態を保存する変数を作っておきます。

bool _active = false;
endDrawer: Drawer(
          child: ListView(children: <Widget>[
        SwitchListTile(
          title: Text("国旗表示"),
          subtitle: Text("日本国の国旗を表示してみよう"),
          value: _active,
          secondary: Icon(Icons.star, color: Colors.teal),
          onChanged: (bool value) {
            setState(() {
              _active = value;
            });
          },
        )

実行結果

endDrawerを引っ張り出すと、トグルスイッチが追加されているかと思います。

フラグを立てたらフラッグが出てくるアプリ

先程作った_activeフラグを用いて動的に国旗表示をやっていきます。 といってもif文を国旗を表示している部分に追加しただけですが…

if (_active == true)
if (_active == true)
              Flag.fromCode(
                FlagsCode.JP,
                height: 300,
              ),

実行結果

初期画面

スイッチ・オン

国旗を表示!!!

コード全文

今回使用したコードは最終的にこのような形になりました。

import 'package:flutter/material.dart';
// import 'package:example/restart_widget.dart';
import 'package:flag/flag.dart';
import 'package:flutter/cupertino.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _active = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'フラグを立てるとフラッグが出てくる',
            ),
            if (_active == true)
              Flag.fromCode(
                FlagsCode.JP,
                height: 300,
              ),
          ],
        ),
      ),
      drawer: Drawer(child: Center(child: Text("ひょっこりはん"))),
      endDrawer: Drawer(
          child: ListView(children: <Widget>[
        SwitchListTile(
          title: Text("国旗表示"),
          subtitle: Text("日本国の国旗を表示してみよう"),
          value: _active,
          secondary: Icon(Icons.star, color: Colors.teal),
          onChanged: (bool value) {
            setState(() {
              _active = value;
            });
          },
        )
      ])),
    );
  }
}

まとめ

今日はシンプルながら実用的な知見が得られました。 drawerはアプリを作っていく上で、使用感の向上に役立つ便利な子です。 可愛がって行きたいものですね。