name27 / flutter

0 stars 0 forks source link

도전과제: 퀴즈앱 Function 클래스, List<Map<String, dynamic>>, examList.insert(index, value) #64

Open name27 opened 1 year ago

name27 commented 1 year ago

수정사항

main_page.dart var _pageController = PageController(viewportFraction: 0.8); QuizCard.dart 최상위 위젯 Padding 삭제 image image 어려웠던 내용: Function 클래스로 선언한 변수로 함수 호출하기 ex) QuizCard.dart에 onCorrect, onIncorrect 해결방법: 인터넷를 아무리 뒤져봐도 안나와서 dartpad로 해결

void main(){
  final Function onCorrect;
  final Function onIncorrect;

  var correctList = ['1','2','3','4','0'];
  onCorrect = (index){correctList.insert(index, '5');};
  onCorrect(5); //계속 onCorrect; 또는 onCorrect();로 main_page에 있는 함수를 호출해봤다가
//인덱스(매개변수)값을 넣어주니 그제야 correctList에 index 5번째에 '5'가 넣어짐
  print(correctList);
}

image 소감: 인터넷에서 찾는 것도 좋지만 비슷한 예시를 만들어서 한 번 해보는게 중요한 듯하다. 실제로 한참 헤맨 내용을 dartpad로 빠르게 해결할 수 있었다.

main.dart

import 'package:flutter/material.dart';
import 'package:quiz_app/main_page.dart';

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

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

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

main_page.dart

// ignore_for_file: prefer_final_fields, avoid_print, prefer_const_constructors, prefer_const_literals_to_create_immutables

import 'package:flutter/material.dart';
import 'package:quiz_app/QuizCard.dart';

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

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

class _MainPageState extends State<MainPage> {
  var _pageController = PageController(viewportFraction: 0.8);
  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": ["녹색", "흰색", "노란색", "파란색"]
    },
  ];
  List<bool> correctList = [];
  onCorrect(int index) {
    if (correctList.length > index) {
      correctList[index] = true;
    } else {
      correctList.insert(index, true);
    }
    _pageController.nextPage(
        duration: Duration(seconds: 1), curve: Curves.easeIn);
    setState(() {});
  }

  onIncorrect(int index) {
    if (correctList.length > index) {
      correctList[index] = false;
    } else {
      correctList.insert(index, false);
    }
    _pageController.nextPage(
        duration: Duration(seconds: 1), curve: Curves.easeIn);
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        elevation: 0,
        leading: IconButton(
            onPressed: () {
              _pageController.previousPage(
                  duration: Duration(seconds: 1), curve: Curves.easeIn);
            },
            icon: Icon(Icons.navigate_before)),
        centerTitle: true,
        title: SizedBox(
          height: 30,
          width: 150,
          child: ListView.builder(
            scrollDirection: Axis.horizontal,
            itemCount: correctList.length,
            itemBuilder: (context, index) => correctList[index]
                ? Padding(
                    padding: const EdgeInsets.all(3.0),
                    child: Icon(Icons.circle_outlined),
                  )
                : Padding(
                    padding: const EdgeInsets.all(3.0),
                    child: Icon(Icons.close),
                  ),
          ),
        ),
        actions: [
          IconButton(
              onPressed: () {
                _pageController.nextPage(
                    duration: Duration(seconds: 1), curve: Curves.easeIn);
              },
              icon: Icon(Icons.navigate_next))
        ],
      ),
      body: Container(
        decoration: BoxDecoration(
            gradient: LinearGradient(
                begin: Alignment.topLeft,
                end: Alignment.bottomRight,
                colors: [Colors.pinkAccent, Colors.blue])),
        child: PageView.builder(
          controller: _pageController,
          scrollDirection: Axis.horizontal,
          itemCount: quizs.length,
          itemBuilder: (context, index) => QuizCard(
              index: index,
              quiz: quizs[index],
              onCorrect: (index) {
                onCorrect(index);
              },
              onIncorrect: (index) {
                onIncorrect(index);
              },
              questionV: "question",
              answerV: "answer",
              optionV: "options"),
        ),
      ),
      floatingActionButton: correctList.length == quizs.length
          ? FloatingActionButton(
              backgroundColor: Colors.white,
              foregroundColor: Colors.black,
              onPressed: () {
                correctList.clear();
                _pageController.animateTo(1,
                    duration: Duration(seconds: 1), curve: Curves.easeIn);
                setState(() {});
              },
              child: Icon(Icons.refresh),
            )
          : null,
    );
  }
}

QuizCard.dart

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,
    required this.questionV,
    required this.answerV,
    required this.optionV,
    required this.index,
  });
  final Map<String, dynamic> quiz;
  final Function onCorrect;
  final Function onIncorrect;
  final int index;
  final String questionV;
  final String answerV;
  final String optionV;

  @override
  Widget build(BuildContext context) {
    return UnconstrainedBox(
      child: Card(
        child: SizedBox(
          width: 280,
          height: 480,
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  quiz[questionV],
                  style: TextStyle(fontWeight: FontWeight.bold),
                ),
                SizedBox(
                  height: 20,
                ),
                for (var i = 0; i < quiz[optionV].length; i++)
                  SizedBox(
                    width: 280,
                    child: ElevatedButton(
                        onPressed: () {
                          if ((quiz[answerV]) == i + 1) {
                            onCorrect(index);
                          } else {
                            onIncorrect(index);
                          }
                        },
                        child: Text(quiz[optionV][i])),
                  ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
name27 commented 1 year ago

Linting 비활성화 analysis_options.yaml 파일에 rules에 prefer_const_constructors: false 추가 image

main.dart

import 'package:flutter/material.dart';
import 'package:quiz_final_app/QuizCard.dart';

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": ["녹색", "흰색", "노란색", "파란색"]
  }
];
void main() {
  runApp(const MyApp());
}

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Icon> result = [];
  var pageController = PageController(viewportFraction: 0.8);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
              colors: [Colors.pinkAccent, Colors.blue],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter),
        ),
        child: Scaffold(
          backgroundColor: Colors.transparent,
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            elevation: 0,
            leading: IconButton(
              onPressed: () {
                pageController.previousPage(
                    duration: Duration(milliseconds: 300),
                    curve: Curves.easeIn);
              },
              icon: Icon(Icons.navigate_before),
            ),
            title: Row(
              mainAxisSize: MainAxisSize.min,
              children: result,
            ),
            centerTitle: true,
            actions: [
              IconButton(
                  onPressed: () {
                    pageController.nextPage(
                        duration: Duration(milliseconds: 300),
                        curve: Curves.easeIn);
                  },
                  icon: Icon(Icons.navigate_next))
            ],
          ),
          body: PageView.builder(
            controller: pageController,
            itemCount: quizs.length,
            itemBuilder: (context, index) => QuizCard(
                quiz: quizs[index],
                onCorrect: () {
                  pageController.nextPage(
                      duration: Duration(milliseconds: 300),
                      curve: Curves.easeIn);
                  result.add(Icon(Icons.circle_rounded));
                  setState(() {});
                },
                onIncorrect: () {
                  pageController.nextPage(
                      duration: Duration(milliseconds: 300),
                      curve: Curves.easeIn);
                  result.add(Icon(Icons.close));
                  setState(() {});
                }),
          ),
          floatingActionButton: result.length == quizs.length
              ? FloatingActionButton(
                  backgroundColor: Colors.white,
                  child: Icon(
                    Icons.refresh,
                    color: Colors.black,
                  ),
                  onPressed: () {
                    result.clear();
                    pageController.jumpTo(0);
                    setState(() {});
                  })
              : null,
        ),
      ),
    );
  }
}

QuizCard.dart

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 Container(
      margin: EdgeInsets.symmetric(horizontal: 16, vertical: 64),
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
          color: Colors.white, borderRadius: BorderRadius.circular(24)),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            quiz["question"],
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
          ),
          SizedBox(
            height: 16,
          ),
          ListView.builder(
            shrinkWrap: true,
            itemCount: quiz["options"].length,
            itemBuilder: (context, index) => ElevatedButton(
              onPressed: () {
                if (quiz["answer"] == index + 1) {
                  onCorrect();
                } else {
                  onIncorrect();
                }
              },
              child: Text(quiz["options"][index]),
            ),
          ),
        ],
      ),
    );
  }
}