Android: Make a Quiz-App

Posted on

Problem

Task description

Make an quiz-app based upon a topic you feel familiar with!

Following requirements

  • Has at least four questions.

  • Following controls are all used at least one time: Button, TextView, EditText, CheckBoxes, RadioButtons.

  • At least one CheckBox-Group uses multi-select.

  • It’s got to have a Submit-Button and a Reset-Button, which empties all controls.

A screenshot of my app in the Emulator

Here’s my Java source-code …

package de.n_or.quizapp;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

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

    public void startEvaluation(View view) {
        String[] answers = evaluateGui();

        int result = evaluateQuiz(answers);

        toastResult(result);
    }

    public String[] evaluateGui() {
        String[] ret = new String[5];
        EditText editTextQuestion1 = findViewById(R.id.question_1);

        CheckBox checkBoxQuestion2Greece = findViewById(R.id.question_2_Greece);
        CheckBox checkBoxQuestion2Burma = findViewById(R.id.question_2_Burma);
        CheckBox checkBoxQuestion2Luxembourg = findViewById(R.id.question_2_Luxembourg);

        Boolean answerQuestion2 = false;

        if (checkBoxQuestion2Greece.isChecked() == true && checkBoxQuestion2Burma.isChecked() == false && checkBoxQuestion2Luxembourg.isChecked() == true) {
            answerQuestion2 = true;
        }

        CheckBox checkBoxQuestion4Capital = findViewById(R.id.question_4_capital);
        CheckBox checkBoxQuestion4Hessia = findViewById(R.id.question_4_hessia);
        CheckBox checkBoxQuestion4Bavaria = findViewById(R.id.question_4_bavaria);

        Boolean answerQuestion4 = false;

        Boolean capital = checkBoxQuestion4Capital.isChecked();
        Boolean hessia = checkBoxQuestion4Hessia.isChecked();
        Boolean bavaria = checkBoxQuestion4Bavaria.isChecked();


        if (capital == false && hessia == false && bavaria == true) {
            answerQuestion4 = true;
        }

        ret[0] = editTextQuestion1.getText().toString().toLowerCase();
        ret[1] = Boolean.toString(answerQuestion2);
        ret[2] = evaluateRadioGroup(R.id.radio_group_question_3).toLowerCase();
        ret[3] = Boolean.toString(answerQuestion4);
        ret[4] = evaluateRadioGroup(R.id.radio_group_question_5).toLowerCase();

        return ret;
    }

    public int evaluateQuiz(String[] answers) {
        int result = 0;
        String[] correctAnswers = {"paris", "true", "south", "true", "germany"};

        for (int i = 0; i < correctAnswers.length; i++) {
            if (answers[i].equals(correctAnswers[i])) {
                result++;
            }
        }

        return result;
    }

    public void toastResult(int result) {
        String message = result + " out of 5. ";

        if (result == 0) {
            message += "Poor luck.";
        } else if (result == 1) {
            message += "You could do better.";
        } else if (result == 2) {
            message += "Quite nice.";
        } else if (result == 3) {
            message += "Really nice.";
        } else if (result == 4) {
            message += "Great!";
        } else if (result == 5) {
            message += "Absolutely awesome!";
        }

        Toast reportResult = Toast.makeText(getApplicationContext(), message,
                Toast.LENGTH_SHORT);
        reportResult.show();
    }

    private String evaluateRadioGroup(int id) {
        RadioGroup radioGroupQuestion;
        RadioButton radioButtonQuestion;

        radioGroupQuestion = findViewById(id);

        int radioButtonId = radioGroupQuestion.getCheckedRadioButtonId();
        radioButtonQuestion = findViewById(radioButtonId);

        if (radioButtonQuestion == null) {
            return "";
        }

        return (String)radioButtonQuestion.getText();
    }

    public void reset(View view) {
        EditText editText = findViewById(R.id.question_1);
        editText.setText("");

        CheckBox checkBox = findViewById(R.id.question_2_Greece);
        checkBox.setChecked(false);

        checkBox = findViewById(R.id.question_2_Burma);
        checkBox.setChecked(false);

        checkBox = findViewById(R.id.question_2_Luxembourg);
        checkBox.setChecked(false);

        RadioGroup radioGroup = findViewById(R.id.radio_group_question_3);
        radioGroup.clearCheck();

        checkBox = findViewById(R.id.question_4_capital);
        checkBox.setChecked(false);

        checkBox = findViewById(R.id.question_4_hessia);
        checkBox.setChecked(false);

        checkBox = findViewById(R.id.question_4_bavaria);
        checkBox.setChecked(false);

        radioGroup = findViewById(R.id.radio_group_question_5);
        radioGroup.clearCheck();
    }
}

The XML for the layout …

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns_android="http://schemas.android.com/apk/res/android"
    xmlns_tools="http://schemas.android.com/tools"
    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="de.n_or.quizapp.MainActivity">

    <ScrollView
        android_layout_width="match_parent"
        android_layout_height="match_parent"
        android_layout_alignParentTop="true"
        android_layout_centerHorizontal="true"
        android_layout_marginTop="0dp">

        <LinearLayout
            android_layout_width="match_parent"
            android_layout_height="wrap_content"
            android_orientation="vertical">

            <TextView
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginBottom="4dp"
                android_text="@string/sub_header"
                android_textAlignment="center"
                android_textSize="22sp" />

            <TextView
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginBottom="12dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="20dp"
                android_text="@string/question1"
                android_textSize="16sp" />

            <EditText
                android_id="@+id/question_1"
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginLeft="16dp" />

            <TextView
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginBottom="6dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="20dp"
                android_text="@string/question2"
                android_textSize="16sp" />

            <CheckBox
                android_id="@+id/question_2_Greece"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_layout_marginBottom="12dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="0dp"
                android_text="@string/checkbox_greece" />

            <CheckBox
                android_id="@+id/question_2_Burma"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_layout_marginBottom="12dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="0dp"
                android_text="@string/checkbox_burma" />

            <CheckBox
                android_id="@+id/question_2_Luxembourg"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_layout_marginBottom="12dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="0dp"
                android_text="@string/checkbox_luxembourg" />

            <TextView
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginBottom="6dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="20dp"
                android_text="@string/question3"
                android_textSize="16sp" />

            <RadioGroup
                android_id="@+id/radio_group_question_3"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_orientation="vertical">

                <RadioButton
                    android_id="@+id/question_3_north"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_layout_marginBottom="0dp"
                    android_layout_marginLeft="16dp"
                    android_layout_marginTop="4dp"
                    android_text="@string/north" />

                <RadioButton
                    android_id="@+id/question_3_east"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_layout_marginBottom="0dp"
                    android_layout_marginLeft="16dp"
                    android_layout_marginTop="2dp"
                    android_text="@string/east" />

                <RadioButton
                    android_id="@+id/question_3_south"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_layout_marginBottom="0dp"
                    android_layout_marginLeft="16dp"
                    android_layout_marginTop="2dp"
                    android_text="@string/south" />

                <RadioButton
                    android_id="@+id/question_3_west"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_layout_marginBottom="6dp"
                    android_layout_marginLeft="16dp"
                    android_layout_marginTop="2dp"
                    android_text="@string/west" />
            </RadioGroup>

            <TextView
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginBottom="6dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="20dp"
                android_text="@string/question4"
                android_textSize="16sp" />

            <CheckBox
                android_id="@+id/question_4_capital"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_layout_marginBottom="12dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="0dp"
                android_text="@string/munich_question_1" />

            <CheckBox
                android_id="@+id/question_4_bavaria"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_layout_marginBottom="12dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="0dp"
                android_text="@string/munich_question_3" />

            <CheckBox
                android_id="@+id/question_4_hessia"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_layout_marginBottom="12dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="0dp"
                android_text="@string/munich_question_2" />

            <TextView
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginBottom="6dp"
                android_layout_marginLeft="16dp"
                android_layout_marginTop="20dp"
                android_text="@string/question5"
                android_textSize="16sp" />

            <RadioGroup
                android_id="@+id/radio_group_question_5"
                android_layout_width="wrap_content"
                android_layout_height="wrap_content"
                android_orientation="vertical">

                <RadioButton
                    android_id="@+id/question_5_germany"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_layout_marginBottom="0dp"
                    android_layout_marginLeft="16dp"
                    android_layout_marginTop="4dp"
                    android_text="@string/germany" />

                <RadioButton
                    android_id="@+id/question_5_poland"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_layout_marginBottom="0dp"
                    android_layout_marginLeft="16dp"
                    android_layout_marginTop="2dp"
                    android_text="@string/poland" />

                <RadioButton
                    android_id="@+id/question_5_denmark"
                    android_layout_width="wrap_content"
                    android_layout_height="wrap_content"
                    android_layout_marginBottom="22dp"
                    android_layout_marginLeft="16dp"
                    android_layout_marginTop="2dp"
                    android_text="@string/denmark" />
            </RadioGroup>

            <Button
                android_id="@+id/evaluate"
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginBottom="22dp"
                android_layout_marginLeft="16dp"
                android_layout_marginRight="16dp"
                android_onClick="startEvaluation"
                android_text="@string/evaluate_button" />

            <Button
                android_id="@+id/reset"
                android_layout_width="match_parent"
                android_layout_height="wrap_content"
                android_layout_marginLeft="16dp"
                android_layout_marginRight="16dp"
                android_onClick="reset"
                android_text="@string/reset_button"
                android_textColor="#ff0033"
                android_textStyle="bold" />

        </LinearLayout>
    </ScrollView>

</LinearLayout>

Hyperlink to my GitHub-Repository.

What would you have done different and why?

Looking forward to reading for comments and answers.

Solution

tldr: you don’t use object orientated programming! the following answer only tells you how to use objects


UI / XML

I would advise you to split your layout into different sub-layouts, so you can re-use the layouts. thus you can easily extend your app in the future.

CODE

I think it would be a good idea to use Question-object. Maybe you would be able to create a factory that create these objects for you – just think of it?

Question capitals = questionFactory.createQuestion(
    QuestionType.MultiChoice, 
    new boolean[]{true, false, true},
    new int[]{R.string.question_2_Greece,
        R.string.question_2_Burma,
        R.string.question_2_Luxembourg}
    );

that would make it easy for you to create any new questions in a simple way. And if you don’t know how to do that you can at least write a simple methods to create the Question-objects Question question = createQuestion(...);

and once this is done it would be easy to use this Question-object for your layout, the layout you add dynamical, not hardcoded in your xml-layout.

View view = findViewById(R.id.scrollview); //FIXME set an ID in your layout
View multiChoiceView = createMultiChoiceView(capitals);
view.addView(multiChoiceView);

you can hence create the sublayout programmatical, if you use the inflater

View multiChoiceView = View.inflate(context, multiChoiceView, yourLinearLayout);

when you creat the layout you can ‘on-the-fly’ set the values and bind the gui to the model. (see this explanation for the different approaches on model/view)

and once this is done you can easily get to your results. Results should be represented as well as an object not a String[], as done in evaluateGui. This way you’re abusing the String[] to represent your results.

private List<Question> questions = ... //see above
private Result validateQuestions(){
    Result result = new Result();
    for (Question question: questions){
        result.addScores(question.getScores());            
    }   
    return result;
}

to validate the result you could also use an enum type instead of counting points.

enum Rating {POOR, MEDICRATE, GOOD, PERFECT};//TODO make a nice toString

public void toastResult(Result result) {
    int scores = result.getScores();
    int amount = result.getAmountQuestions();
    Rating rating = result.getRating();

    String message = MessageFormat.format("you had {0} of {1} - your rating is {2}", scores, amount, rating);
    Toast.makeText(getApplicationContext(), message,
            Toast.LENGTH_SHORT).show();

Leave a Reply

Your email address will not be published. Required fields are marked *