2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Flutterでクイズアプリケーションを作成する方法

Last updated at Posted at 2023-06-14

まず、簡単なクイズアプリケーションを作成する。

スクリーンショット 2023-06-14 10.46.21.png
選択肢のリストの項目をクリックすると次の問題に進む。
スクリーンショット 2023-06-14 10.46.34.png
次の問題が表示される。

ユーザーが選択肢を選んだときの正誤判定や、すべての問題を解き終えたときのフィードバックは本記事では取り扱っていない。

1. 問題文、選択肢、正解を保持するための設計(question.dartの作成)

1-1. Questionクラスの作成

まず、それぞれの問題、その選択肢、正解を関連付けて保持するためのQuestionクラスを定義する。

class Question {
  String question;
  List<String> choices;
  int answerIndex;

  Question(this.question, this.choices, this.answerIndex);
}

このクラスには、問題文、選択肢リスト、正解のインデックスが含まれる。問題文はString型、選択肢リストはString型のリストであり、正解は選択肢リストの中のインデックスとすることで整数型で保持する。

1-2 Questionクラスの使用例

Question q1 = Question(
 'What is the capital of France?', ['Paris', 'Berlin', 'London', 'Madrid'], 0
);

Questionクラスを用いて、上記のように新しい問題を作成する。この例では、「フランスの首都は何か?」という問題文に対し、「パリ、ベルリン、ロンドン、マドリード」の選択肢があり、その中で最初の選択肢(インデックス0)が正解となる。

1-3 question.dartの作成

Questionクラスをquestion.dartというファイル名で保存する。

2. 問題を表示するシンプルなFlutterアプリケーションの作成(main.dartの作成)

画面に問題と選択肢を表示する簡単なアプリを作成する。これらの問題と選択肢は前述のcreateQuestion関数を使って作成する。

5つの問題をリストに追加し、それらを順番に表示する。選択肢をクリックすると次の問題に進むようにする。5つの問題を順番に表示するために、現在の問題のインデックスを管理する必要がある。

// main.dart

import 'package:flutter/material.dart';
import 'question.dart'; // Importing Question class 

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

class QuestionApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Question App',
      home: QuizScreen(),
    );
  }
}

class QuizScreen extends StatefulWidget {
  QuizScreen({Key? key}) : super(key: key);

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

class _QuizScreenState extends State<QuizScreen> {
  late List<Question> questions;
  int currentIndex = 0;

  void _incrementCounter(){
    setState((){
      currentIndex = (currentIndex + 1) % questions.length;
    });
  }

  @override
  void initState() {
    super.initState();
    questions = [
      Question('What is the capital of France?', ['Paris', 'Berlin', 'London', 'Madrid'], 0),
      Question('What is the capital of Germany?', ['Paris', 'Berlin', 'London', 'Madrid'], 1),
      Question('What is the capital of UK?', ['Paris', 'Berlin', 'London', 'Madrid'], 2),
      Question('What is the capital of Spain?', ['Paris', 'Berlin', 'London', 'Madrid'], 3),
      Question('What is the capital of Italy?', ['Paris', 'Berlin', 'London', 'Madrid', 'Rome'], 4),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Question App'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              questions[currentIndex].question,
              style: Theme.of(context).textTheme.headline5,
            ),
            ...questions[currentIndex].choices.map((choice) => ListTile(
                  title: Center(
                    child: Text(choice),
                  ),
                  onTap: _incrementCounter,
                )).toList(),
          ],
        ),
      ),
    );
  }
}

ここで、'question.dart'をインポートすることで、Questionクラスが利用できるようになる。

1. QuestionAppクラス
これはStatelessWidgetを継承するクラスで、アプリケーションのメインウィジェットとなる。アプリケーションのホーム画面としてQuizScreenを設定している。

2. QuizScreenクラス
StatefulWidgetを継承するクラスで、状態(ここでは現在の問題)を持つウィジェットである。

3. _QuizScreenStateクラス
QuizScreenウィジェットの状態を管理するクラスである。クイズの問題リスト(questions)と現在の問題のインデックス(currentIndex)を保持する。initStateメソッドによって、初期化時に5つの問題がquestionsリストに追加される。

3.1. initStateメソッド
initStateメソッドで5つの問題を作成し、questionsリストに追加する。各問題はcreateQuestion関数を使用して作成され、問題文、選択肢のリスト、正解のインデックスを引数として渡す。

3.2. buildメソッド
buildメソッドでは、アプリケーションのUIを定義する。Scaffoldウィジェットを使用してアプリケーションの基本的なレイアウト(AppBarとBody)を作成する。Body部分では現在の問題とその選択肢を表示する。選択肢はListTileウィジェットとして表示され、タップすると次の問題に進むようにonTapコールバックが設定されている。

3.2.1. Textウィジェット
Textウィジェットは、現在の問題(questions[currentIndex].question)を表示する。ススタイルはTheme.of(context).textTheme.headline5を適用し、アプリのテーマに従った見た目が適用される。

3.2.2. 選択肢のリスト
questions[currentIndex].choices.map((choice) => ListTile(title: Text(choice), onTap: () {...}))という表現は、選択肢を一つずつ取り出し(.map((choice) => ...))、それぞれの選択肢にListTileウィジェットを適用している。

ListTileウィジェットはリスト内の各項目に適用し、そのタイトルに選択肢のテキストを配置する。

onTap: () {...}は、ユーザーがその選択肢をタップしたときの振る舞いを定義しする。現在は、どの選択肢がタップされても次の問題に移動する。これはsetState関数を用いてcurrentIndexを更新することで実現される。また、% questions.lengthにより質問リストの範囲を超えないようにしている。

3.2.3. スプレッド演算子...
... と .toList() という表現はスプレッド演算子と呼ばれ、リスト内の要素を別のリストに展開する。これにより、各選択肢が個別のListTileとしてColumnウィジェット内に配置される。

これらを組み合わせることで、質問とその選択肢が画面上に表示され、ユーザーが選択肢をタップすると次の質問に移動するという動作を実現している。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?