# How to Create a Custom Quiz Widget for Your FlutterFlow App

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 25-30 min
- Compatibility: FlutterFlow Free+
- Last updated: March 2026

## TL;DR

Build a quiz Component using a PageView where each page displays one question with radio-button answer options loaded from a Firestore questions subcollection. Track the current question index and selected answers in Component State. On the final page, calculate the score by comparing selected answers to correctAnswerIndex fields, display results, and save the score to a quiz_results collection with userId, quizId, and timestamp.

## Building an Interactive Quiz in FlutterFlow

Quizzes are used in e-learning, assessments, surveys, and gamification. This tutorial builds a complete quiz flow: loading questions from Firestore, displaying them one at a time in a PageView, tracking answers, calculating the score, and saving results. The quiz Component is reusable for multiple quizzes.

## Before you start

- A FlutterFlow project with Firestore configured
- A quizzes collection and a questions subcollection in Firestore
- Basic understanding of Component State and PageView in FlutterFlow

## Step-by-step guide

### 1. Set up the Firestore data model for quizzes and questions

Create a quizzes collection with fields: title (String), description (String), questionCount (int). Create a questions subcollection under each quiz document with fields: questionText (String), options (String array with 4 items), correctAnswerIndex (int, 0-3), order (int). Add at least 3-5 question documents for testing, with order values 1 through 5 so they display in sequence.

**Expected result:** Firestore has a quizzes collection with a questions subcollection containing ordered quiz questions.

### 2. Build the quiz page with a PageView for question navigation

Create a new page called QuizPage with a Route Parameter quizId (String). Add a Backend Query on the page that queries the questions subcollection under quizzes/{quizId}/questions, ordered by the order field ascending. Add a PageView widget configured for horizontal scrolling with page snapping enabled. Disable user swiping by setting physics to NeverScrollableScrollPhysics — navigation should only happen via the Next button to prevent skipping questions.

**Expected result:** A PageView loads with one page per question from Firestore, and users cannot swipe between questions.

### 3. Display each question with selectable answer options

Inside each PageView page, add a Column: a LinearPercentIndicator at the top showing progress (currentIndex / totalQuestions), the question text bound to the questionText field in Headline Small style, and below it a Column of four Radio Button options or ChoiceChips. Bind the options to the options array field. Use Component State to track selectedAnswerIndex for the current question. When the user taps an option, update the selected index and enable the Next button.

**Expected result:** Each question page shows the question text, four selectable answer options, and a progress bar.

### 4. Track answers and navigate between questions with a Next button

Add Component State: selectedAnswers (int List, default empty). On the Next button tap: add the current selectedAnswerIndex to the selectedAnswers list, clear the selection, and call Animate to Next Page on the PageView. On the last question, change the button text to Submit. When Submit is tapped, add the final answer, then navigate to the results view. Use Component State currentIndex (int) incremented on each Next tap to track position and control button text.

**Expected result:** Each answer is saved to the selectedAnswers list as the user progresses through questions.

### 5. Calculate the score and display results on the final page

After the last question, calculate the score: loop through selectedAnswers comparing each value to the corresponding question's correctAnswerIndex. Count matches for the total score. Display a results Column: Lottie animation (success if score > 70%, try-again if below), score text (e.g., '4 out of 5'), percentage, and a retake button. Save the result to a quiz_results collection: create a document with userId, quizId, score, totalQuestions, percentage, and timestamp.

**Expected result:** The results page shows the score with visual feedback and saves the result to Firestore.

## Complete code example

File: `FlutterFlow Quiz Setup`

```text
FIRESTORE DATA MODEL:
  quizzes/{quizId}
    title: String
    description: String
    questionCount: int
    └── questions/{questionId}
          questionText: String
          options: ["Option A", "Option B", "Option C", "Option D"]
          correctAnswerIndex: int (0-3)
          order: int (1, 2, 3...)

PAGE: QuizPage
  Route Parameter: quizId (String)
  Backend Query: questions subcollection, order by order asc

COMPONENT STATE:
  currentIndex: int = 0
  selectedAnswerIndex: int = -1
  selectedAnswers: List<int> = []

WIDGET TREE:
  Column
    ├── LinearPercentIndicator
    │     percent: (currentIndex + 1) / questions.length
    ├── PageView (horizontal, NeverScrollableScrollPhysics)
    │     └── Per question:
    │           Column
    │             ├── Text (questionText, Headline Small)
    │             ├── SizedBox (20)
    │             └── RadioButtonGroup or ChoiceChips
    │                   options: question.options
    │                   selected: selectedAnswerIndex
    └── Button ("Next" or "Submit")
          Enabled: selectedAnswerIndex >= 0
          On Tap:
            1. Add selectedAnswerIndex to selectedAnswers list
            2. Reset selectedAnswerIndex to -1
            3. If not last: Animate to Next Page + increment currentIndex
            4. If last: Calculate score + save to quiz_results + show results

SCORE CALCULATION:
  score = 0
  for i in 0..selectedAnswers.length:
    if selectedAnswers[i] == questions[i].correctAnswerIndex:
      score += 1
  percentage = score / questions.length * 100
```

## Common mistakes

- **Using App State for quiz answers instead of Component State** — App State persists to disk. If the user exits mid-quiz and returns later, old answers load from the previous attempt, corrupting the current quiz session. Fix: Use Component State or Page State for in-progress quiz data. These are ephemeral and reset when the page is left.
- **Allowing users to swipe between PageView questions freely** — Users skip ahead to see all questions or go back and change answers after seeing later questions, undermining quiz integrity. Fix: Set PageView physics to NeverScrollableScrollPhysics so navigation only happens via the Next button.
- **Not disabling the Next button until an answer is selected** — Users accidentally advance without selecting an answer, resulting in a missing entry in the selectedAnswers array and incorrect score calculation. Fix: Set the Next button's enabled Conditional property to selectedAnswerIndex >= 0. Grey it out until an option is tapped.

## Best practices

- Use Component State (not App State) for quiz answers to prevent persistence across sessions
- Disable PageView swiping with NeverScrollableScrollPhysics for controlled navigation
- Show a progress indicator (LinearPercentIndicator) so users know how many questions remain
- Disable the Next button until an answer is selected to prevent blank submissions
- Store questions in Firestore so quizzes can be updated without modifying the app
- Save quiz results with userId, quizId, score, and timestamp for analytics
- Add a retake button on the results page that resets state and navigates back to question 1

## Frequently asked questions

### Can I randomize question order?

Firestore does not support random ordering in queries. Fetch all questions and shuffle the list in a Custom Function before displaying. Or add a random field to each question and order by it.

### How do I show which answers were correct after submission?

On the results page, display each question with the user's answer and the correct answer. Use Conditional Styling to color correct answers green and incorrect ones red.

### Can I add a timer to each question?

Yes. Add a countdown timer using a Custom Action that decrements a Page State integer every second. When it reaches zero, auto-submit the current answer (or skip) and move to the next question.

### How do I prevent users from retaking the quiz?

Check the quiz_results collection on page load. If a document exists for the current userId + quizId, redirect to the results page instead of starting the quiz.

### Can quizzes have images in the questions?

Yes. Add an imageUrl field to the questions document. Display an Image widget above the question text, bound to the imageUrl field. Use Conditional Visibility to hide it when imageUrl is empty.

### Can RapidDev help build a complete e-learning quiz platform?

Yes. RapidDev can build quiz systems with timed questions, scoring algorithms, leaderboards, certificates, and analytics dashboards.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-custom-quiz-widget-for-your-flutterflow-app
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-custom-quiz-widget-for-your-flutterflow-app
