Quiz app using jetpack compose

Quiz app using jetpack compose

Quiz app using jetpack compose

How to create a quiz app using jetpack compose?
Welcome to codingbihar.com, Today we will create a quiz app using jetpack compose a modern toolkit. As Google has released a new version of Android studio  Iguana | 2023.2.1, so we will use it for creating this Quiz App. But you can use the latest version of android studio for this project. We create this project without using any library so you don't need to bothered just relax and read the tutorial carefully.

Quiz app using jetpack compose contains only four files 

1. MainActivity - This is the default Activity created when we create a new Empty Compose Project, We will add here Quiz App a composable in which we create our UI for Quiz App.

2. QuizApp - This is the main composable file of our app in this composable components  we will design our App's UI App's first screen shows the question and four clickable options and a button to show a next question after completing the a result screen show the score.

3. Data Class  Question - In this data class we define the type of our data as String or Int. which we are using in this app.

4. QuestionsProvider - This is a file where we will store a list of questions with options and their correct answer.

Steps To create a Quiz App Using Jetpack Compose

Step 1- Create a New Project and select Empty Activity and click on Next then a new window open write the name of your app in my case it is ComposeApp and click on finish after a few second you have MainActivity with default Greeting Composable.
Create a New Project and select Empty Activity

compose Quiz App

Step 2 - Remove the unnecessary code and update the MainActivity according to the below

Copy this code →

package com.example.composequizapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import com.example.composequizapp.ui.theme.ComposeQuizAppTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeQuizAppTheme {
               
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = Color.DarkGray
                ) {
                    ComposeQuizApp()
                }
            }
        }
    }
}
Step 3 - QuizApp
Copy this code →

package com.example.composequizapp

import...

@Composable
fun ComposeQuizApp() {
    var currentQuestionIndex by remember { mutableIntStateOf(0) }
    var selectedOption by remember { mutableStateOf("") }
    var isOptionSelected by remember { mutableStateOf(false) }
    var areOptionsClickable by remember { mutableStateOf(true) }
    var questionNumber by remember { mutableIntStateOf(1) }
    var scoreNumber by remember { mutableIntStateOf(0) }
    if (currentQuestionIndex < questions.size) {
        val currentQuestion = questions[currentQuestionIndex]
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(16.dp)
        ) {
            Text(text = stringResource(id = R.string.app_name),
                color = Color.White,
                style = MaterialTheme.typography.displayMedium)
            Divider(Modifier.height(2.dp).fillMaxWidth())
            Spacer(modifier = Modifier.height(16.dp))
            Text(text = "Question $questionNumber", style = MaterialTheme.typography.headlineLarge, color = Color.Yellow)
            Text(text = "Score $scoreNumber", style = MaterialTheme.typography.headlineLarge, color = Color.Green)
            Text(text = currentQuestion.text, style = MaterialTheme.typography.headlineMedium, color = Color.White)
            Spacer(modifier = Modifier.height(16.dp))
            OptionList(
                options = currentQuestion.options,
                onOptionSelected = {
                    selectedOption = it
                    isOptionSelected = true
                    areOptionsClickable = false
                    if (it == currentQuestion.correctAnswer) {
                            // Update the score if the selected option is correct
                        scoreNumber++
                    }
                                   },
                correctOption = currentQuestion.correctAnswer,
                selectedOption = selectedOption,
                areOptionsClickable = areOptionsClickable
            )
            Spacer(modifier = Modifier.height(32.dp))
            NextButton(
                onNext = {
                        questionNumber++
                        scoreNumber=scoreNumber++
                        // Move to the next question
                        currentQuestionIndex++
                        selectedOption = ""
                        isOptionSelected = false
                        areOptionsClickable = true
                         },
                isEnabled = isOptionSelected
            )
        }
    } else {
            // Quiz completed
        QuizCompletedScreen(
            scoreNumber=scoreNumber,
            onRestart = {
                // Restart the quiz
                questionNumber=1
                currentQuestionIndex = 0
                scoreNumber=0
                selectedOption = ""
                isOptionSelected = false
                areOptionsClickable = true
            }
        )
    }
}

@Composable
fun OptionList(
    options: List,
    onOptionSelected: (String) -> Unit,
    correctOption: String,
    selectedOption: String,
    areOptionsClickable: Boolean
) {
    LazyColumn {
        items(options.size) { index ->
            OutlinedCard(colors =CardDefaults.outlinedCardColors(Color.Black),
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(8.dp)
                    .border(
                        width = 2.dp,
                        color = when {
                            index == options.indexOf(selectedOption) && selectedOption == correctOption -> Color.Green
                            index == options.indexOf(selectedOption) -> Color.Red
                            else -> Color.White
                                     },
                        shape = MaterialTheme.shapes.medium
                    )
                    .clickable {
                        if (areOptionsClickable) {
                            onOptionSelected(options[index])
                        }
                    }
            ) {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.SpaceBetween,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Text(
                        text = options[index],
                        style = MaterialTheme.typography.headlineSmall,
                        color = when{
                            index == options.indexOf(selectedOption) && selectedOption == correctOption -> Color.Green
                            index == options.indexOf(selectedOption) -> Color.Red
                            else -> Color.White
                                    },
                        modifier = Modifier.padding(16.dp)
                    )
                    Icon(
                        imageVector = when {
                            index == options.indexOf(selectedOption) && selectedOption == correctOption -> Icons.Default.Check
                            index == options.indexOf(selectedOption) -> Icons.Filled.Clear
                            else -> Icons.Filled.KeyboardArrowRight },
                            contentDescription = null,
                            tint = when {
                                index == options.indexOf(selectedOption) && selectedOption == correctOption -> Color.Green
                                index == options.indexOf(selectedOption) -> Color.Red
                                else -> MaterialTheme.colorScheme.primary
                            },
                            modifier = Modifier
                                .size(64.dp)
                                .padding(end = 20.dp)
                        )

                    }
                }
            }
        }
    }
@Composable
fun NextButton(onNext: () -> Unit, isEnabled: Boolean) {
    OutlinedButton(
        onClick = { if (isEnabled) onNext() },
        modifier = Modifier.fillMaxWidth(),
        enabled = isEnabled,
        shape = RectangleShape,
        // This line controls the button's click ability
    ) {
        Text(
            text = "Next",
            fontWeight = FontWeight.ExtraBold,
            style = MaterialTheme.typography.headlineLarge
        )
    }
}

@Composable
fun QuizCompletedScreen(onRestart: () -> Unit,scoreNumber: Int) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = "Congratulations! You have completed the quiz.\n\n" +
                    "Total Questions: ${questions.size}\n\n" +
                    "Correct Questions:$scoreNumber\n\n" +
                    "Incorrect Question: ${questions.size - scoreNumber}\n\n",
            style = MaterialTheme.typography.headlineLarge,
            modifier = Modifier.fillMaxWidth(),
            color = Color.White
        )
        val scorePercentage = (scoreNumber.toFloat() / questions.size.toFloat()) * 100
        Text(
            text = "Your Score: $scoreNumber/${questions.size} (${scorePercentage.toInt()}%)",
            color = Color.Blue,
            style = MaterialTheme.typography.displayMedium
        )
        Spacer(modifier = Modifier.height(26.dp))
        Button(
            onClick = onRestart,
            modifier = Modifier.fillMaxWidth()
        ) {
            Text(text = "Restart Quiz")
        }
    }
}
Data Class Question 
Copy this code →

package com.example.composequizapp

data class Question(
    val id: Int,
    val text: String,
    val options: List,
    val correctAnswer:String
)
Question
Copy this code →

package com.example.composeapp

val questions = listOf(
    Question(
        id = 1,
        text = "What is Android?",
        options = listOf("A programming language", "A type of robot", "A mobile operating system", "A web browser"),
        correctAnswer = "A mobile operating system"
    ),
    Question(
        id = 2,
        text = "Who initially developed Android?",
        options = listOf("Microsoft", "Apple", "Android Inc.", "Google"),
        correctAnswer = "Android Inc."
    ),
    Question(
        id = 3,
        text = "What programming language is primarily used for Android app development?",
        options = listOf("Python", "C++", "Java", "Swift"),
        correctAnswer = "Java"
    ),
    Question(
        id = 4,
        text = "What is an APK in Android?",
        options = listOf("A type of permission", "A configuration file", "Android Package Kit", "A debugging tool"),
        correctAnswer = "Android Package Kit"
    ),
    Question(
        id = 5,
        text = "What is Android Jetpack?",
        options = listOf("A game engine for Android", "A debugging tool", "A set of libraries, tools, and guidelines", "A new version of the Android OS"),
        correctAnswer = "A set of libraries, tools, and guidelines"
    ),
    Question(
        id = 5,
        text = "What is the Google Play Store?",
        options = listOf("A code repository", "A tool for app analytics", "An app marketplace for Android", "A development environment"),
        correctAnswer = "An app marketplace for Android"
    ),
    // Add more questions as needed
)
OUTPUT:
Quiz app using jetpack compose

Quiz app using jetpack compose

Quiz app using jetpack compose

Download the example of quiz app from Indus App Store
 
Get it on Indus Appstore
Previous Post Next Post