카테고리 없음
퀴즈앱만들기
신승호.
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
- 주어진 데이터를 활용하여 퀴즈앱을 만듭니다.
- 앱 배경색은 다음의 색상들을 Gradient로 표시합니다.
- Colors.pinkAccent
- Colors.blue
- 퀴즈 위젯은 퀴즈 데이터 수 만큼 생성되며, 데이터에 퀴즈 데이터를 추가할 때 추가된 퀴즈도 위젯으로 되어 보여집니다.
- 각 퀴즈의 보기들 중 하나를 클릭하였을 경우, 상단에 스코어가 위젯형태로 표시되며, 다음 페이지로 넘어갑니다.
- 정답시 Icon(Icons.circle_outlined) 가 추가됩니다.
- 오답시 Icon(Icons.close) 가 추가됩니다.
- 모든 문제를 풀었을 경우, 하단에 FAB가 표시되며 이 때 표시되는 위젯은 Icon(Icons.refresh)가 됩니다.
- 해당 버튼을 클릭하면, 모든 스코어가 초기화되며 첫 퀴즈로 이동됩니다.
- 제공되는 일부 코드가 있습니다.
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]));
})
],
),
),
);
}
}