Trắc nghiệm: Đúng hay sai
Thuộc phần Dự án trong hành trình Flutter của Coddy. Bài học 11 trên 36.
Chạm vào một đáp án, bài trắc nghiệm sẽ báo ngay: màu xanh lá nếu bạn chọn đúng, màu đỏ nếu bạn chọn sai, còn đáp án đúng luôn có màu xanh lá để bạn ghi nhớ.
Trạng thái cần ghi nhớ bạn đã chạm vào đáp án nào. int? _picked là null cho đến khi bạn chạm vào một đáp án, vì vậy _picked != null có nghĩa là bạn đã trả lời. Sau đó, các nút sẽ ngừng nhận thao tác: dòng đầu tiên của _pick là một câu lệnh bảo vệ.
void _pick(int answer) {
if (_answered) return;
setState(() {
_picked = answer;
});
}Một hàm nhỏ sẽ xác định màu của từng nút. null nghĩa là “không có màu riêng”, và nút sẽ giữ màu theo giao diện:
Color? _colorFor(int answer) {
if (!_answered) return null;
if (answer == _question.correct) return Colors.green;
if (answer == _picked) return Colors.red;
return null;
}Các nút giờ cần vị trí, chứ không chỉ cần văn bản, vì vậy vòng lặp đếm: for (int i = 0; i < question.answers.length; i++) chạy với i lần lượt là 0, 1, 2 và 3.
Thử thách
KhóTô màu các đáp án:
- thêm
int? _picked, các getter_questionvà_answered, cùng các phương thức_pickvà_colorFortrong phần lý thuyết - lặp qua các đáp án theo vị trí bằng
for (int i = 0; ...) - mỗi nút gọi
_pick(i);backgroundColorcủa nút là_colorFor(i), và văn bản trên nút có màu trắng khi nút có màu
Tự làm thử
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const QuizScreen(),
);
}
}
class Question {
const Question(this.text, this.answers, this.correct);
final String text;
final List<String> answers;
final int correct;
}
const List<Question> questions = [
Question('Which widget stacks its children from top to bottom?', ['Row', 'Column', 'Stack', 'Wrap'], 1),
Question('Which language do you write Flutter apps in?', ['Kotlin', 'Swift', 'Dart', 'JavaScript'], 2),
Question('What does setState do?', ['Rebuilds the widget', 'Saves the app', 'Closes the screen', 'Plays a sound'], 0),
Question('Which widget shows a list you can scroll?', ['Container', 'SizedBox', 'Padding', 'ListView'], 3),
Question('Which widget adds space around its child?', ['Padding', 'Center', 'Icon', 'Text'], 0),
];
class QuizScreen extends StatefulWidget {
const QuizScreen({super.key});
@override
State<QuizScreen> createState() => _QuizScreenState();
}
class _QuizScreenState extends State<QuizScreen> {
int _index = 0;
@override
Widget build(BuildContext context) {
final question = questions[_index];
final textTheme = Theme.of(context).textTheme;
return Scaffold(
appBar: AppBar(title: const Text('Flutter Quiz')),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(question.text, style: textTheme.headlineSmall),
const SizedBox(height: 24),
for (String answer in question.answers)
Padding(
padding: const EdgeInsets.only(bottom: 12),
child: FilledButton.tonal(
style: FilledButton.styleFrom(
padding: const EdgeInsets.all(16),
),
onPressed: () {},
child: Text(answer),
),
),
],
),
),
);
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Dự án
1Dự án: Danh sách việc cần làm
Danh sách việc cần làm: Danh sách công việcDanh sách việc cần làm: Thêm công việc4Dự án: Theo dõi thói quen
Theo dõi thói quen: Thói quen của bạnTheo dõi thói quen: TuầnTự luyện tập: Trình biên dịch Flutter online