Challenge:When the user has answered all the questions, he displays a toast message and gives the percentage form
Hi,evrybody:
I am actually working through this great book and am solving now the second challenge exercises of chapter 3,and the title is: when the user has finished all, he displays a toast message and gives a percentage score .
But i have no idea about this,as toast messages should not be String type?
You can show toasts with strings too. You can use either a resource ID or a string value.
This version of makeText
can operate off of a String value: https://developer.android.com/reference/android/widget/Toast.html#makeText(android.content.Context, java.lang.CharSequence, int).
I can’t open this link.
can you share code in this net?
Thank you !
Here is my solution for the two challenges in chapter 3. The code is marked.
package com.bignerdranch.android.geoquiz;
…
// challenge 3.1
import java.util.ArrayList;
public class QuizActivity extends AppCompatActivity {
private static final String TAG = "QuizActivity";
private static final String KEY_INDEX = "index";
private Button mTrueButton;
private Button mFalseButton;
private Button mNextButton;
private TextView mQuestionTextView;
// challenge 3.1
private ArrayList<Integer> mQuestionAsked = new ArrayList<Integer>(6);
// challenge 3.2
private int mTrueAnswer = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, “onCreate(Bundle) called”);
setContentView(R.layout.activity_quiz);
if (savedInstanceState != null) {
mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0);
// challenge 3.1
mQuestionAsked = savedInstanceState.getIntegerArrayList("myArray");
}
mQuestionTextView = (TextView) findViewById(R.id.question_text_view);
mQuestionTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
updateQuestion();
}
});
…
private void updateQuestion() {
int question = mQuestionBank[mCurrentIndex].getTextResId();
mQuestionTextView.setText(question);
/* challenge 3.1................*/
mFalseButton.setVisibility(View.VISIBLE);
mTrueButton.setVisibility(View.VISIBLE);
for (Integer i = 0; i < mQuestionAsked.size(); i++) {
if (mCurrentIndex == mQuestionAsked.get(i)) {
mFalseButton.setVisibility(View.INVISIBLE);
mTrueButton.setVisibility(View.INVISIBLE);
}
}
/*...............................*/
// challenge 3.2
int resultResId = (mTrueAnswer*100) / 6;
if (mQuestionAsked.size() > 5) {
Toast.makeText(this, Integer.toString(resultResId)+"% correct answers", Toast.LENGTH_LONG)
.show();
}
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.i(TAG, "onSaveInstanceState");
savedInstanceState.putInt(KEY_INDEX, mCurrentIndex);
// challenge 3.1
savedInstanceState.putIntegerArrayList("myArray", mQuestionAsked);
}
private void checkAnswer(boolean userPressedTrue) {
boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();
// challenge 3.1
mQuestionAsked.add(mCurrentIndex);
mFalseButton.setVisibility(View.INVISIBLE);
mTrueButton.setVisibility(View.INVISIBLE);
/*...............................*/
int messageResId = 0;
if (userPressedTrue == answerIsTrue) {
messageResId = R.string.correct_toast;
// challenge 3.2
mTrueAnswer = mTrueAnswer + 1;
} else {
messageResId = R.string.incorrect_toast;
}
Toast.makeText(this, messageResId, Toast.LENGTH_SHORT)
.show();
}
}
My solution:
...
private int correctAnswers = 0;
...
private void checkAnswer(boolean userPressedTrue) {
questionsAnswered[currentIndex] = true;
setButtonsEnabled(false);
boolean answerIsTrue = questionBank[currentIndex].isAnswerTrue();
int messageResId;
if (userPressedTrue == answerIsTrue) {
messageResId = R.string.toast_correct;
correctAnswers++;
} else {
messageResId = R.string.toast_incorrect;
}
Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();
calculateScore();
}
private void calculateScore() {
// check all questions answered
for (boolean answered : questionsAnswered) {
if (!answered) return;
}
// all answered, show message
int score = correctAnswers * 100 / questionBank.length;
String message = getString(R.string.toast_score, score);
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
And my strings.xml
with placeholder
<resources>
...
<string name="toast_score">You have %1$d%% correct answers!</string>
...
</resources>
My solution for both challenges
Comments are encouraged
public class QuizActivity extends AppCompatActivity {
    private static final String KEY_INDEX = "index";
    private static final String KEY_SCORE = "score";
    private static final String KEY_ANSWERED = "answered";
    private static final int QUESTION_GRADE = 1;
    private Button mTrueButton;
    private Button mFalseButton;
    private Button mNextButton;
    private Button mPrevButton;
    private TextView mQuestionTextView;
    private Question[] mQuestionBank = new Question[]{
        new Question(R.string.question_australia, true),
        new Question(R.string.question_oceans, true),
        new Question(R.string.question_middleeast, false),
        new Question(R.string.question_africa, false),
        new Question(R.string.question_americas, true),
        new Question(R.string.question_asia, true),
    };
    private int mCurrentIndex = 0;
    private boolean[] mQuestionStatus = new boolean[mQuestionBank.length];
    private int[] mScore = new int[mQuestionBank.length];
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_quiz);
        if (savedInstanceState != null) {
            mCurrentIndex = savedInstanceState.getInt(KEY_INDEX);
            if (savedInstanceState.containsKey(KEY_ANSWERED)) {
                mQuestionStatus = savedInstanceState.getBooleanArray(KEY_ANSWERED);
            }
            if (savedInstanceState.containsKey(KEY_SCORE)) {
                mScore = savedInstanceState.getIntArray(KEY_SCORE);
            }
        }
        // question text view
        mQuestionTextView = (TextView) findViewById(R.id.question_text_view);
        /*
        mQuestionTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                nextQuestion();
            }
        });
        */
        // True button
        mTrueButton = (Button) findViewById(R.id.true_button);
        mTrueButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkAnswer(true);
            }
        });
        // False button
        mFalseButton = (Button) findViewById(R.id.false_button);
        mFalseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkAnswer(false);
            }
        });
        // Next button
        mNextButton = (Button) findViewById(R.id.next_button);
        mNextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                nextQuestion();
            }
        });
        // Previous button
        mPrevButton = (Button) findViewById(R.id.previous_button);
        mPrevButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                previousQuestion();
            }
        });
        // At app run, display the first question
        updateQuestion();
    }
    @Override
    public void onStart() {
        super.onStart();
    }
    @Override
    public void onResume() {
        super.onResume();
    }
    @Override
    public void onPause() {
        super.onPause();
    }
    @Override
    public void  onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putInt(KEY_INDEX, mCurrentIndex);
        savedInstanceState.putBooleanArray(KEY_ANSWERED, mQuestionStatus);
        savedInstanceState.putIntArray(KEY_SCORE, mScore);
    }
    @Override
    public void onStop() {
        super.onStop();
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
    /*
     * Updates the text view with the question statement
     * corresponding to current index
     */
    private void updateQuestion() {
        int question = mQuestionBank[mCurrentIndex].getTextResId();
        mQuestionTextView.setText(question);
        // if question has not been answered already, activate answer buttons
        if (!mQuestionStatus[mCurrentIndex % mQuestionBank.length]) {
            activateAnswerButton();
        } else {
            deactivateAnswerButton();
        }
    }
    /*
     * Display a toast message indicating correctness of user answer
     * @param userPressedTrue A falg indicating whether the user answered True
     */
    private void checkAnswer(boolean userPressedTrue) {
        // Mark question as answered
        mQuestionStatus[mCurrentIndex % mQuestionBank.length] = true;
        deactivateAnswerButton();
        int toastResId;
        boolean isCorrectAnswer = userPressedTrue == mQuestionBank[mCurrentIndex].isAnswerTrue();
        if (isCorrectAnswer) {
            mScore[mCurrentIndex % mQuestionBank.length] = QUESTION_GRADE;
            toastResId = R.string.correct_toast;
        } else {
            // when user answered again, report his inccorect answeres(depend on business logic)
            mScore[mCurrentIndex % mQuestionBank.length] = 0;
            toastResId = R.string.incorrect_toast;
        }
        Toast toast = Toast.makeText(QuizActivity.this, toastResId,
                Toast.LENGTH_LONG);
        toast.setGravity(Gravity.BOTTOM, 0, 0);
        toast.show();
        if (allAnswered()) {
            DisplayScore();
            reset();
        }
    }
    /*
     * Checks whether the user has answered all the questions
     * @return true if the user has answered all questions
     */
    private boolean allAnswered() {
        for (boolean status : mQuestionStatus) {
            if (!status) {
                return false;
            }
        }
        return true;
    }
    /*
     * Reset score and answered questions
     */
    private void reset() {
        // set all questions unanswered
        for (int i = 0; i < mQuestionStatus.length ; i++) {
            mQuestionStatus[i] = false;
        }
        // set all scores to zero
        for (int i = 0; i < mScore.length ; i++) {
            mScore[i] = 0;
        }
    }
    /*
     * Displays the score
     */
    private void DisplayScore() {
        Toast.makeText(this,
                "Score: " + getScore() + "%",
                Toast.LENGTH_LONG).show();
    }
    /*
     * Gets the score as a percentage
     * @return The score
     */
    private double getScore() {
        double score = 0;
        for (int i = 0; i < mScore.length ; i++) {
            score += mScore[i];
        }
        return  (score / mQuestionBank.length) * 100;
    }
    /*
     * Proceeds to next question
     */
    private  void nextQuestion() {
        // keep looping forward in the questions
        mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
        updateQuestion();
    }
    /*
     * Returns to previous question
     */
    private  void previousQuestion() {
        // keep looping backward in the questions
        if(mCurrentIndex == 0) {
            mCurrentIndex = mQuestionBank.length - 1;
        }  else {
            mCurrentIndex = mCurrentIndex - 1;
        }
        updateQuestion();
    }
    /*
     * Deactivates True and False buttons
     */
    private void deactivateAnswerButton() {
        mTrueButton.setEnabled(false);
        mFalseButton.setEnabled(false);
    }
    /*
     * Activates True and False buttons
     */
    private void activateAnswerButton() {
        mTrueButton.setEnabled(true);
        mFalseButton.setEnabled(true);
    }
private int mTrueAnswer = 0;
private int mCurrentNumberAnswered = 0;
private void updateQuestion(){
mTrueButton.setEnabled(!mQuestionAnswered[mCurrentIndex]);
mFalseButton.setEnabled(!mQuestionAnswered[mCurrentIndex]);
int question = mQuestionnBank[mCurrentIndex].getTextResId();
mQuestionTextView.setText(question);
**mCurrentNumberAnswered++;**
**int resultResId = (mTrueAnswer*100)/6;**
** if(mCurrentNumberAnswered==mQuestionnBank.length+1){**
** Toast.makeText(this, Integer.toString(resultResId)+"% correct answers", Toast.LENGTH_LONG).show();**
}
}
if(userPressedTrue == answerIsTrue){
messageResId = R.string.correct_toast;
mTrueAnswer = mTrueAnswer +1;}else{ messageResId = R.string.incorrect_toast; } Toast.makeText(this,messageResId,Toast.LENGTH_SHORT).show(); }
I am trying to solve this challenge but I still don’t know what the toast message is not displayed.
Can anyone help please?
Below is my code:
private fun checkAnswer(userAnswer: Boolean) {
binding.falseButton.isEnabled = false
binding.trueButton.isEnabled = false
questionBank[currentIndex].answered = true
val correctAnswer = questionBank[currentIndex].answer
val messageResId = if (userAnswer == correctAnswer) {
R.string.correct_toast
} else {
R.string.incorrect_toast
}
if (isAllQuestionsAnswered()) {
val score = getString(R.string.percentage_toast, calculateScore())
Toast.makeText(this, score, Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show()
}
correctAnswers++
}
private fun isAnswered(index: Int) {
val isQuestionAnswered = questionBank[index].answered
binding.trueButton.isEnabled = !isQuestionAnswered
binding.falseButton.isEnabled = !isQuestionAnswered
}
private fun isAllQuestionsAnswered(): Boolean {
for (question in questionBank) {
if (question.answered) {
return false
}
}
return true
}
private fun calculateScore():Double {
return (correctAnswers.toDouble() / questionBank.size) * 100
}