Re:birth エンジニアリング

Flultterとテックブログと時々iOS

Flutterで4択クイズアプリのレイアウトを実装する

本日はFlutterで4択クイズっぽいアプリを作っていきます。 特に体系的に学習するという意味ではないので企画倒れになるかもしれません。 Flutterのスキルアップとしてはちょうどいい題材かなと思っています。

アプリのデザイン構成

これから何日間かにわたって開発するアプリのデザイン・レイアウトはこのようになります。

f:id:qed805:20200301181710p:plain
アプリのデザイン(Sketch案)

至ってシンプルですね。Sketchでサクッと作ってみました。 英語の文法問題で、ある問題文に対して4つの選択肢が与えられ回答を選択すると言った流れになります。 英語の問題自体はどっかから拝借してきました。

将来的には問題と選択肢をAPIから取得して来て動的に変更できるようにすることを想定しています。

デザインのレイアウト

それではいきなりですが、初日に出来上がったデザイン・レイアウトのスクリーンショットを張ってみます。

f:id:qed805:20200301181013p:plain
4択クイズのデザインレイアウト

Skecthファイルの作成からこのデザインが組み上げられるまで約3時間ほどでした。 レイアウトを作っていると、昔iOSアプリを作るためにstoryboardと格闘していた頃を思い出しますね。 つまり、やっぱりFlutterでレイアウトを組み立てる作業で時間がかかりました。

次にこのデザイン時のサンプルコードを貼ります。 これからクラスの分割や定数処理などで過去記事を復習するため全てmain.dartウィジェットを書きました。

main.dart

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

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

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('文法問題'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            Container(
              height: 70,
              color: Colors.red,
              child: Center(
                child: Text(
                  '(x)に入る単語を答えよ。',
                  style: TextStyle(fontSize: 20),
                ),
              ),
            ),
            Container(
              height: 70,
              color: Colors.green,
              child: Center(
                child: Text(
                  'Q1',
                  style: TextStyle(fontSize: 18),
                ),
              ),
            ),
            Container(
              color: Colors.yellow,
              child: Padding(
                padding: const EdgeInsets.all(20.0),
                child: Center(
                  child: Text(
                    'The weather in Merizo is very (x) year-round, though there are showers almost daily from December through March.',
                    style: TextStyle(fontSize: 20),
                  ),
                ),
              ),
            ),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(50.0, 30.0, 50.0, 50.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    SizedBox(
                        width: double.infinity,
                        height: 50,
                      child: RaisedButton(
                        child: Text('agreeable'),
                        onPressed: null,
                      )
                    ),
                    SizedBox(
                      width: double.infinity,
                      height: 50,
                      child: RaisedButton(
                        child: Text('agree'),
                        onPressed: null,
                      ),
                    ),
                    SizedBox(
                      width: double.infinity,
                      height: 50,
                      child: RaisedButton(
                        child: Text('agreement'),
                        onPressed: null,
                      ),
                    ),
                    SizedBox(
                      width: double.infinity,
                      height: 50,
                      child: RaisedButton(
                        child: Text('agreeably'),
                        onPressed: null,
                      ),
                    ),
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

ウィジェット間の位置感覚をあとで調整するためウィジェットの背景色に色をつけています。

利用したウィジェットは次に挙げるものです。

  • Container
  • Center
  • Column
  • Text

marginやpaddingなどの調整で役にたったウィジェット

  • Expanded
  • SizedBox
  • Padding
  • Container

これらです。

レイアウトを組んでいて悩んだポイントは、

  1. デザインの部品から作成すべきか
  2. 部品の配置から整えていくべきか

こちらになります。 というのもアプリ開発で一番つらい部分というのは最後の部品の位置調整だったりします。 今回は2番の配置の調整を頑張りました。

今後の予定

ここからクイズアプリを完成させるまでの作業としては

  • 選択肢のボタンのデザインを調整する
  • 選択肢のボタンをカスタムクラスにして分割する
  • 問題のクラスを作成する
  • 選択肢ボタンをタップしたあとの挙動

などやるべきことが沢山ありますね。