Menu
CoddyTech
flag Ar iconالعربيةdown icon

الاختبار القصير: شاشة النتائج

جزء من قسم المشاريع في رحلة Flutter على Coddy. الدرس 16 من 36.

عند الإجابة عن السؤال الأخير، ينبغي أن ينتهي الاختبار على شاشة مستقلة تعرض نتيجتك. هذا عنصر واجهة مستخدم ثانٍ، ResultsScreen، ويأخذك إليه Navigator.push.

تحتاج شاشة النتائج إلى رقمين: الدرجة وعدد الأسئلة. وتحصل عليهما عبر المُنشئ، على شكل وسيطين مسمّيين مطلوبين: required

class ResultsScreen extends StatelessWidget {
  const ResultsScreen({super.key, required this.score, required this.total});

  final int score;
  final int total;
  ...
}

في السؤال الأخير، يُعرض على الزر «عرض النتائج» بدلًا من «التالي». تتولى الطريقة نفسها _next الأمرين: ففي السؤال الأخير، تنتقل إلى شاشة النتائج ثم تعود، لذا لا يتجاوز الفهرس نهاية القائمة أبدًا.

if (_isLast) {
  Navigator.push(context, MaterialPageRoute(
    builder: (context) => ResultsScreen(score: _score, total: questions.length),
  ));
  return;
}
challenge icon

التحدي

متوسط

أنه الاختبار في شاشة النتائج:

  • اكتب شاشة ResultsScreen تتضمن Scaffold وAppBar بعنوان Results، وفي المنتصف مع مساحة داخلية قدرها 24 بكسل، اعرض You scored 3 out of 5 (بالأرقام الفعلية) باستخدام نمط headlineSmall الخاص بالسمات
  • أظهر الزر بعد كل إجابة، مع تسمية See results للسؤال الأخير وNext للأسئلة الأخرى
  • في السؤال الأخير، تنقل _next إلى شاشة النتائج

جرّب بنفسك

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;
  int? _picked;
  int _score = 0;

  Question get _question => questions[_index];
  bool get _answered => _picked != null;
  bool get _isLast => _index == questions.length - 1;

  void _pick(int answer) {
    if (_answered) return;
    setState(() {
      _picked = answer;
      if (answer == _question.correct) {
        _score++;
      }
    });
  }

  void _next() {
    setState(() {
      _index++;
      _picked = null;
    });
  }

  Color? _colorFor(int answer) {
    if (!_answered) return null;
    if (answer == _question.correct) return Colors.green;
    if (answer == _picked) return Colors.red;
    return null;
  }

  @override
  Widget build(BuildContext context) {
    final question = _question;
    final textTheme = Theme.of(context).textTheme;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter Quiz'),
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 16),
            child: Center(
              child: Text('Score: $_score', style: textTheme.titleMedium),
            ),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              'Question ${_index + 1} of ${questions.length}',
              style: textTheme.labelLarge,
            ),
            const SizedBox(height: 8),
            LinearProgressIndicator(
              value: (_index + 1) / questions.length,
              minHeight: 8,
              borderRadius: BorderRadius.circular(4),
            ),
            const SizedBox(height: 24),
            Text(question.text, style: textTheme.headlineSmall),
            const SizedBox(height: 24),
            for (int i = 0; i < question.answers.length; i++)
              Padding(
                padding: const EdgeInsets.only(bottom: 12),
                child: FilledButton.tonal(
                  style: FilledButton.styleFrom(
                    backgroundColor: _colorFor(i),
                    foregroundColor: _colorFor(i) == null ? null : Colors.white,
                    padding: const EdgeInsets.all(16),
                  ),
                  onPressed: () => _pick(i),
                  child: Text(question.answers[i]),
                ),
              ),
            if (_answered) ...[
              const SizedBox(height: 12),
              Text(
                _picked == question.correct
                    ? 'Correct!'
                    : 'The answer is ${question.answers[question.correct]}',
                textAlign: TextAlign.center,
                style: textTheme.titleMedium,
              ),
              const SizedBox(height: 16),
              if (!_isLast)
                FilledButton(
                  onPressed: _next,
                  child: const Text('Next'),
                ),
            ],
          ],
        ),
      ),
    );
  }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس المشاريع

تدرّب بنفسك: مترجم Flutter عبر الإنترنت