0. 들어가기
-. flutter에서 json object를 사용해본다.
-. map 함수를 이용해서 다수의 widget을 추가해본다.
1. json object를 이용한 퀴즈 출력
-. json 형태로 이루어진 퀴즈를 작성해보자. DnD 성향 테스트를 예시로 작성해봤다. 출처링크
1) json object 선언
-. 파이썬의 dict 형에 너무 익숙해져서 js에서 json을 사용하려니 매우 힘들었다. Map으로 구조를 만들어가면서 선언해야 한다..
//dnd Alignment object 선언
Map<String, Map<String, Object>> dndAlignment = {
"1": {
"question":
"Family elders are expressing disapproval of you to the rest of the family. Do you:",
"answers": {
"1": "Accept the criticism and change your ways?",
"2": "Seek a compromise with them?",
"3":
"Besmirch the reputation of those expressing disapproval as you ignore their scorn?",
"4": "Silence them any way you can?"
}
},
"2": {
"question":
"Would you give up a promising career to aid the family in time of need?",
"answers": {
"1": "In a heartbeat.",
"2": "Yes, with some reluctance.",
"3": "Only if I was certain I'd be able to return to my career soon.",
"4": "No."
}
}
};
2) 질의응답 만들기
-. 우선 문제 번호를 questionIndex로 설정하고, 버튼 클릭 시 해당 값을 1씩 더하는 함수를 만들었다. (앞에 것 재활용)
//퀴즈번호 생성
int questionIndex = 1;
//버튼 클릭 시 다음 번호로
void buttonClicked() {
setState(() {
questionIndex += 1;
});
}
-. 다음으로, 문제 텍스트와 답변 텍스트들을 뽑아서 body에 문제와 답변을 출력해야 하는데 json 안의 value로 json이 들어가 있어서 조금은 지저분한 변수 호출이 된다.
body: Column(
children: [
Question(dndAlignment["$questionIndex"]?['question'] as String),
ElevatedButton(
onPressed: buttonClicked,
child: Text((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["1"] as String),
),
ElevatedButton(
onPressed: buttonClicked,
child: Text((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["2"] as String)),
ElevatedButton(
onPressed: buttonClicked,
child: Text((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["3"] as String)),
ElevatedButton(
onPressed: buttonClicked,
child: Text((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["4"] as String)),
],
)),
-. 그럭저럭 출력은 된다. (매우 허접해 보이지만)
3) 개선해야 할 점들
-. 당장 몇가지 문제가 보인다.
1) 답변의 길이에 따라 버튼 폭이 달라짐
2) 문제 번호가 넘어가면 에러 발생 (아래 영상 참고)
3) 그리고 코드 측면에서 각 답변 (1~4) 번호를 직접 입력해서 구현했기에 코드가 지저분할 뿐 아니라, 답변 갯수가 달라지거나 하면 에러가 발생할 것이다.
2. map으로 답변 버튼 출력
-. javascript엔 배열로부터 새로운 배열을 만들어주는 map 함수가 있다. 예제링크
-. dart에서도 동일하게 사용할 수 있으니 함 시도해보자.
1) 답변 버튼 위젯 만들기
-. 우선 코드를 정리해서 답변 버튼을 출력하는 answer 위젯을 만들었다. 하는김에 위젯 폭과 색도 조금 수정했다.
answer.dart
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
final String answer;
final VoidCallback quizHandler;
Answer(this.answer, this.quizHandler);
@override
Widget build(BuildContext context) {
// TODO: implement build
// return Text(question);
return Container(
width: double.infinity,
alignment: Alignment.centerLeft,
margin: const EdgeInsets.all(10),
// color: Colors.blue[200],
child: ElevatedButton(
onPressed: quizHandler,
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(const Size(double.infinity, 40)),
backgroundColor: MaterialStateProperty.all(Colors.red),
// foregroundColor: MaterialStateProperty.all(Colors.transparent),
),
child: Text(
answer,
style: const TextStyle(fontSize: 20),
textAlign: TextAlign.left,
),
),
);
}
}
----
main.dart
import './answer.dart';
...
body: Column(
children: [
Question(dndAlignment["$questionIndex"]?['question'] as String),
Answer((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["1"] as String, buttonClicked),
Answer((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["2"] as String, buttonClicked),
Answer((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["3"] as String, buttonClicked),
Answer((dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)["4"] as String, buttonClicked),
],
)
2) map 함수 사용하기
-. 정리된 코드에서는 answers의 키("1" ~ "4") 를 제외하고는 모두 동일한 코드로 Answer 위젯을 호출한다. 조금 더럽지만 깔끔한 (...) 코드가 되었다.
children: [
Question(dndAlignment["$questionIndex"]?['question'] as String),
...(dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)
.keys
.map((answerNum) {
return Answer(
(dndAlignment["$questionIndex"]?['answers']
as Map<String, String>)[answerNum] as String,
buttonClicked);
}).toList(),
],
-. 이제 답변 갯수가 몇개든 대응 가능한 앱이 만들어졌다. (문제를 3번까지로 늘리고) 테스트를 해보면 2번의 5개 답변 / 3번의 3개 답변에 대해 의도한 대로 대응하는 것을 확인할 수 있다.
-. 하지만 여전히 문제 배열을 벗어나면 에러가 발생하는 문제가 남아있다. 다음 포스트에서 해결하자..
'mobile' 카테고리의 다른 글
[flutter] if문 사용법, 퀴즈 결과 보여주기 (0) | 2022.09.25 |
---|---|
[flutter] json object + map (2) (0) | 2022.08.14 |
[flutter] widget 모듈화 + 스타일링 (0) | 2022.08.08 |
[flutter] flutter 위젯(widget) (0) | 2022.06.26 |
[flutter] flutter app 작성 예제 (0) | 2021.04.27 |
최근댓글