Sabtu, 04 Juli 2026

Android - Java XML - Quiz 1

 Here is a clean, complete template for a multiple-choice quiz using standard Android Java and an XML layout. It features custom styling for the options using a RadioGroup and handles the question state dynamically.

1. The Layout (activity_main.xml)

This UI uses a TextView for the question, a RadioGroup to hold the choices (ensuring only one can be selected at a time), and a Button to submit the answer.

XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_width"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="24dp"
    android:gravity="center_vertical">

    <!-- Question Counter -->
    <TextView
        android:id="@+id/tv_question_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Question 1 of 3"
        android:textSize="14sp"
        android:textColor="#757575"
        android:layout_marginBottom="8dp" />

    <!-- The Question -->
    <TextView
        android:id="@+id/tv_question"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="What is the capital city of France?"
        android:textSize="22sp"
        android:textStyle="bold"
        android:textColor="#212121"
        android:layout_marginBottom="24dp" />

    <!-- Options Container -->
    <RadioGroup
        android:id="@+id/rg_options"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="32dp">

        <RadioButton
            android:id="@+id/rb_option1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:layout_marginBottom="8dp"
            android:text="London"
            android:textSize="16sp" />

        <RadioButton
            android:id="@+id/rb_option2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:layout_marginBottom="8dp"
            android:text="Berlin"
            android:textSize="16sp" />

        <RadioButton
            android:id="@+id/rb_option3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:layout_marginBottom="8dp"
            android:text="Paris"
            android:textSize="16sp" />

        <RadioButton
            android:id="@+id/rb_option4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:layout_marginBottom="8dp"
            android:text="Madrid"
            android:textSize="16sp" />
    </RadioGroup>

    <!-- Action Button -->
    <Button
        android:id="@+id/btn_submit"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:text="Submit Answer"
        android:textSize="16sp" />

</LinearLayout>

2. The Logic (MainActivity.java)

This class manages the quiz state, validates whether an option was chosen, tallies the score, and handles advancing to the next question.

Java
package com.example.quizapp;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private TextView tvQuestionNumber, tvQuestion;
    private RadioGroup rgOptions;
    private RadioButton rbOption1, rbOption2, rbOption3, rbOption4;
    private Button btnSubmit;

    // Quiz Data Arrays
    private final String[] questions = {
            "What is the capital city of France?",
            "Which planet is known as the Red Planet?",
            "What is the largest mammal on Earth?"
    };

    private final String[][] options = {
            {"London", "Berlin", "Paris", "Madrid"},
            {"Earth", "Mars", "Jupiter", "Saturn"},
            {"Elephant", "Blue Whale", "Giraffe", "Orca"}
    };

    // Index tracking for the correct answers (0-indexed)
    private final int[] correctAnswers = {2, 1, 1}; // Paris, Mars, Blue Whale

    private int currentQuestionIndex = 0;
    private int score = 0;

    @Override
    protected void Bundle) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize UI Elements
        tvQuestionNumber = findViewById(R.id.tv_question_number);
        tvQuestion = findViewById(R.id.tv_question);
        rgOptions = findViewById(R.id.rg_options);
        rbOption1 = findViewById(R.id.rb_option1);
        rbOption2 = findViewById(R.id.rb_option2);
        rbOption3 = findViewById(R.id.rb_option3);
        rbOption4 = findViewById(R.id.rb_option4);
        btnSubmit = findViewById(R.id.btn_submit);

        // Load the first question
        loadQuestion();

        // Handle button clicks
        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int selectedId = rgOptions.getCheckedRadioButtonId();

                // 1. Validation check: Ensure they picked an option
                if (selectedId == -1) {
                    Toast.makeText(MainActivity.this, "Please select an answer", Toast.LENGTH_SHORT).show();
                    return;
                }

                // 2. Identify which button was clicked
                RadioButton selectedRadioButton = findViewById(selectedId);
                int selectedAnswerIndex = rgOptions.indexOfChild(selectedRadioButton);

                // 3. Check if the answer is correct
                if (selectedAnswerIndex == correctAnswers[currentQuestionIndex]) {
                    score++;
                    Toast.makeText(MainActivity.this, "Correct!", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "Wrong Answer!", Toast.LENGTH_SHORT).show();
                }

                // 4. Advance or show results
                currentQuestionIndex++;
                if (currentQuestionIndex < questions.length) {
                    loadQuestion();
                } else {
                    showResults();
                }
            }
        });
    }

    private void loadQuestion() {
        // Reset the selection container
        rgOptions.clearCheck();

        // Update Text
        String progressText = "Question " + (currentQuestionIndex + 1) + " of " + questions.length;
        tvQuestionNumber.setText(progressText);
        tvQuestion.setText(questions[currentQuestionIndex]);
        
        // Update Options
        rbOption1.setText(options[currentQuestionIndex][0]);
        rbOption2.setText(options[currentQuestionIndex][1]);
        rbOption3.setText(options[currentQuestionIndex][2]);
        rbOption4.setText(options[currentQuestionIndex][3]);

        // If it's the final question, change button text
        if (currentQuestionIndex == questions.length - 1) {
            btnSubmit.setText("Finish Quiz");
        }
    }

    private void showResults() {
        // Disable choices and update UI to show score
        tvQuestionNumber.setText("Quiz Completed");
        tvQuestion.setText("Your final score is: " + score + " / " + questions.length);
        rgOptions.setVisibility(View.GONE);
        
        // Turn the button into a restart button
        btnSubmit.setText("Restart Quiz");
        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Reset state parameters
                currentQuestionIndex = 0;
                score = 0;
                rgOptions.setVisibility(View.VISIBLE);
                btnSubmit.setText("Submit Answer");
                
                // Re-wire original behavior
                recreate(); 
            }
        });
    }
}

How the mechanics work under the hood:

  • rgOptions.clearCheck(): It is critical to clear the previous selection before loading a new question. Otherwise, if a user selected option 3 on question 1, option 3 will remain checked when question 2 displays.

  • rgOptions.indexOfChild(...): This helper maps the active RadioButton directly to its integer index inside the group layout ($0, 1, 2,$ or $3$). This allows for quick math comparisons against the correctAnswers index array without needing to parse the actual string labels.

Tidak ada komentar: