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.
Prerequisites
- 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
Set up the Firestore data model for quizzes and questions
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.
Build the quiz page with a PageView for question navigation
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.
Display each question with selectable answer options
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.
Track answers and navigate between questions with a Next button
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.
Calculate the score and display results on the final page
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 working example
1FIRESTORE DATA MODEL:2 quizzes/{quizId}3 title: String4 description: String5 questionCount: int6 └── questions/{questionId}7 questionText: String8 options: ["Option A", "Option B", "Option C", "Option D"]9 correctAnswerIndex: int (0-3)10 order: int (1, 2, 3...)1112PAGE: QuizPage13 Route Parameter: quizId (String)14 Backend Query: questions subcollection, order by order asc1516COMPONENT STATE:17 currentIndex: int = 018 selectedAnswerIndex: int = -119 selectedAnswers: List<int> = []2021WIDGET TREE:22 Column23 ├── LinearPercentIndicator24 │ percent: (currentIndex + 1) / questions.length25 ├── PageView (horizontal, NeverScrollableScrollPhysics)26 │ └── Per question:27 │ Column28 │ ├── Text (questionText, Headline Small)29 │ ├── SizedBox (20)30 │ └── RadioButtonGroup or ChoiceChips31 │ options: question.options32 │ selected: selectedAnswerIndex33 └── Button ("Next" or "Submit")34 Enabled: selectedAnswerIndex >= 035 On Tap:36 1. Add selectedAnswerIndex to selectedAnswers list37 2. Reset selectedAnswerIndex to -138 3. If not last: Animate to Next Page + increment currentIndex39 4. If last: Calculate score + save to quiz_results + show results4041SCORE CALCULATION:42 score = 043 for i in 0..selectedAnswers.length:44 if selectedAnswers[i] == questions[i].correctAnswerIndex:45 score += 146 percentage = score / questions.length * 100Common mistakes when creating a Custom Quiz Widget for Your FlutterFlow App
Why it's a problem: Using App State for quiz answers instead of Component State
How to avoid: Use Component State or Page State for in-progress quiz data. These are ephemeral and reset when the page is left.
Why it's a problem: Allowing users to swipe between PageView questions freely
How to avoid: Set PageView physics to NeverScrollableScrollPhysics so navigation only happens via the Next button.
Why it's a problem: Not disabling the Next button until an answer is selected
How to avoid: 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
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a quiz feature in FlutterFlow using PageView for question navigation, Firestore for storing questions (text, options array, correctAnswerIndex), Component State for tracking answers, and a results page that calculates and saves the score. Give me the complete widget tree and action flows.
Create a page with a progress bar at the top, a large text area for the question, four selectable option buttons below, and a Next button at the bottom.
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.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation