카테고리 없음

퀴즈앱만들기

신승호. 2023. 2. 12. 23:16

데이터

List<Map<String, dynamic>> quizs = [
  {
    "question": "의학적으로 얼굴과 머리를 구분하는 기준은 어디일까요?",
    "answer": 2,
    "options": ["코", "눈썹", "귀", "머리카락"]
  },
  {
    "question": "다음 중 바다가 아닌 곳은?",
    "answer": 3,
    "options": ["카리브해", "오호츠크해", "사해", "지중해"]
  },
  {
    "question": "심청이의 아버지 심봉사의 이름은?",
    "answer": 2,
    "options": ["심전도", "심학규", "심한길", "심은하"]
  },
  {
    "question": "심청전에서 심청이가 빠진 곳은 어디일까요?",
    "answer": 4,
    "options": ["정단수", "육각수", "해모수", "인당수"]
  },
  {
    "question": "택시 번호판의 바탕색은?",
    "answer": 3,
    "options": ["녹색", "흰색", "노란색", "파란색"]
  }
];

Requirements

  1. 주어진 데이터를 활용하여 퀴즈앱을 만듭니다.
  2. 앱 배경색은 다음의 색상들을 Gradient로 표시합니다.
    • Colors.pinkAccent
    • Colors.blue
  3. 퀴즈 위젯은 퀴즈 데이터 수 만큼 생성되며, 데이터에 퀴즈 데이터를 추가할 때 추가된 퀴즈도 위젯으로 되어 보여집니다.
  4. 각 퀴즈의 보기들 중 하나를 클릭하였을 경우, 상단에 스코어가 위젯형태로 표시되며, 다음 페이지로 넘어갑니다.
    • 정답시 Icon(Icons.circle_outlined) 가 추가됩니다.
    • 오답시 Icon(Icons.close) 가 추가됩니다.
  5. 모든 문제를 풀었을 경우, 하단에 FAB가 표시되며 이 때 표시되는 위젯은 Icon(Icons.refresh)가 됩니다.
    • 해당 버튼을 클릭하면, 모든 스코어가 초기화되며 첫 퀴즈로 이동됩니다.
  6. 제공되는 일부 코드가 있습니다.
class QuizCard extends StatelessWidget {
  const QuizCard({super.key, required this.quiz, required this.onCorrect, required this.onIncorrect});
  final Map<String, dynamic> quiz;
  final Function onCorrect;
  final Function onIncorrect;

  @override
  Widget build(BuildContext context) {
			...

내 메인코드...

import 'package:flutter/material.dart';
import 'package:quizs_app/quizcard.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MainPage(),
    );
  }
}

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  var score = [];
  var pageController = PageController(viewportFraction: 0.7);
  List<Map<String, dynamic>> quizs = [
    {
      "question": "의학적으로 얼굴과 머리를 구분하는 기준은 어디일까요?",
      "answer": 2,
      "options": ["코", "눈썹", "귀", "머리카락"]
    },
    {
      "question": "다음 중 바다가 아닌 곳은?",
      "answer": 3,
      "options": ["카리브해", "오호츠크해", "사해", "지중해"]
    },
    {
      "question": "심청이의 아버지 심봉사의 이름은?",
      "answer": 2,
      "options": ["심전도", "심학규", "심한길", "심은하"]
    },
    {
      "question": "심청전에서 심청이가 빠진 곳은 어디일까요?",
      "answer": 4,
      "options": ["정단수", "육각수", "해모수", "인당수"]
    },
    {
      "question": "택시 번호판의 바탕색은?",
      "answer": 3,
      "options": ["녹색", "흰색", "노란색", "파란색"]
    }
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        extendBodyBehindAppBar: true,
        body: Container(
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [Colors.pinkAccent, Colors.blue])),
          child: Column(
            children: [
              SizedBox(
                height: 150,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    IconButton(
                      onPressed: () {
                        pageController.previousPage(
                            duration: Duration(seconds: 1),
                            curve: Curves.easeIn);
                      },
                      icon: Icon(Icons.arrow_back_ios),
                      color: Colors.white,
                    ),
                    ListView.builde(                              //OX넣어야함
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,             //  주로 리스트 안에 리스트를 구현하거나 스크롤이 없는 리스트를 만들 때 이 방법을 사용
                        itemCount: score.length,
                        itemBuilder: (context, index) {
                         return score[index];
                        }),
                    IconButton(
                      onPressed: () {
                        pageController.nextPage(
                            duration: Duration(seconds: 1),
                            curve: Curves.easeIn);
                      },
                      icon: Icon(Icons.arrow_forward_ios),
                      color: Colors.white,
                    )
                  ],
                ),
              ),
              Expanded(
                  child: PageView.builder(
                controller: pageController,
                physics: BouncingScrollPhysics(),
                itemCount: quizs.length,
                itemBuilder: (context, index) {
                  return QuizCard(
                      quiz: quizs[index],
                      onCorrect: () {
                        setState(() {
                          score.add(Icon(Icons.circle_outlined));
                          pageController.nextPage(
                              duration: Duration(seconds: 1),
                              curve: Curves.easeIn);
                        });
                      },
                      onIncorrect: () {
                        setState(() {
                          score.add(Icon(Icons.close));
                          pageController.nextPage(
                              duration: Duration(seconds: 1),
                              curve: Curves.easeIn);
                        });
                      });
                },
              )),
            ],
          ),
        ),
        floatingActionButton: AnimatedOpacity(
          opacity: score.length==quizs.length   ? 1 : 0,                //스코어개수와 퀴즈개수와 같으면 투명도1 아니면0
          duration: Duration(seconds: 1),
          child: FloatingActionButton(
            backgroundColor: Colors.white,
            foregroundColor: Colors.black,
            onPressed: (() {
              setState(() {
                score.clear();
              });
              pageController.jumpTo(0);
            }),
            child: Icon(Icons.refresh),
          ),
        ));
  }
}
 
 
 

아래는 퀴즈카드코드...

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class QuizCard extends StatelessWidget {
  const QuizCard(
      {super.key,
      required this.quiz,
      required this.onCorrect,
      required this.onIncorrect});
  final Map<String, dynamic> quiz;
  final Function onCorrect;
  final Function onIncorrect;
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.fromLTRB(15, 0, 15, 70),
      child: Card(
        elevation: 10,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(32)),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Padding(
              padding: const EdgeInsets.all(8),
              child: Text(
                quiz['question'].toString(),
                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
              ),
            ),
            ListView.builder(
                shrinkWrap: true,     //(Column안에 리스트뷰사용)리스트 자식높이의 합만큼으로 영역고정
                padding: EdgeInsets.fromLTRB(8, 0, 8, 0),
                itemCount: quiz['options'].length,
                itemBuilder: (context, index) {
                  return ElevatedButton(
                      onPressed: () {
                        (quiz['answer'] == index+1)          //컴퓨터가 이해하려면 +1해줘야함
                            ? onCorrect()
                            : onIncorrect(); //answer이 index와 같으면 OnCorrect를 아니면 onInCorrect 호출
                      },
                      child: Text(quiz['options'][index]));
                })
          ],
        ),
      ),
    );
  }
}