Menu
CoddyTech

Cuestionario: Siguiente pregunta

Parte de la sección Proyectos del Journey de Flutter de Coddy. Lección 12 de 36.

Una pregunta no es un cuestionario. Después de responder, un botón Siguiente debería llevarte a la siguiente pregunta, y una línea en la parte superior debería indicar en qué pregunta estás.

Pasar a la siguiente pregunta implica dos cambios en un solo setState: el índice aumenta y se olvida la respuesta, así que la nueva pregunta empieza sin colores:

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

El botón solo tiene sentido una vez que hayas respondido, y no en la última pregunta, donde no hay una siguiente (la pantalla de resultados vendrá después). Un if de colección lo añade solo en ese caso: if (_answered && !_isLast) FilledButton(...).

Las personas cuentan desde 1; las listas, desde 0. La etiqueta muestra _index + 1: 'Question ${_index + 1} of ${questions.length}'. La forma ${...} te permite poner una expresión completa en una cadena, no solo un nombre.

challenge icon

Desafío

Intermedio

Avanza por las preguntas:

  • añade un getter _isLast que sea true en la última pregunta, y el método _next de la teoría
  • encima de la pregunta, muestra Question 1 of 5 (con los números reales) con el estilo labelLarge del tema y, después, deja 24 píxeles de espacio
  • debajo de las respuestas, una vez que hayas respondido y la pregunta no sea la última, muestra un FilledButton con la etiqueta Next que llame a _next

Pruébalo tú mismo

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;

  Question get _question => questions[_index];
  bool get _answered => _picked != null;

  void _pick(int answer) {
    if (_answered) return;
    setState(() {
      _picked = answer;
    });
  }

  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')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            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]),
                ),
              ),
          ],
        ),
      ),
    );
  }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Proyectos

Practica por tu cuenta: Compilador de Flutter online