Solutions for this Chapter

I have noticed that the application crashes when compiling the project after adding the Image Buttons when the android:src attributes are added.

Can someone explain why GeoQuiz has stopped error could be happening?

1 Like

I noticed to. How to solve this?

I didn’t see any such error like this …

You must change the declarations for nextButton and prevButton to ImageButtons.
private lateinit var prevButton: ImageButton
private lateinit var nextButton: ImageButton

1 Like

Everything works fine for me

@Gawitt Maybe provide a stacktrace for further debugging!. But I’d second @curion4 (his solution seems to be whats needed).

Here’s my solutions, if someone has better or different if they could please share so I can learn better or alternative options.

activity_main.xml:

    <ImageButton
        android:id="@+id/prev_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:background="@color/design_default_color_primary"
        android:contentDescription="@string/prev_button"
        android:padding="8dp"
        android:src="@drawable/arrow_left" />

    <ImageButton
        android:id="@+id/next_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/design_default_color_primary"
        android:contentDescription="@string/next_button"
        android:padding="8dp"
        android:src="@drawable/arrow_right" />
    
</LinearLayout>

MainActivty.kt:

private lateinit var nextButton: ImageButton // changed these from Buttons to ImageButtons
private lateinit var prevButton: ImageButton

// in onCreate method I added:

    prevButton.setOnClickListener {
        if (currentIndex > 0) {
            currentIndex = (currentIndex - 1)
            updateQuestion()
        } else {
            currentIndex = questionBank.size - 1
            updateQuestion()
        }
    }

    questionTextView.setOnClickListener {
        currentIndex = (currentIndex + 1) % questionBank.size
        updateQuestion()
    }

Back Button:

    backButton.setOnClickListener{
        if (currentIndex == 0) {
            currentIndex = questionBank.size - 1
        }else{
            currentIndex -= 1
        }
        updateQuestion()

Next Burtton:

nextButton.setOnClickListener {
        if (currentIndex == questionBank.size-1) {
            currentIndex = 0
        }else{
            currentIndex += 1
        }
         updateQuestion()
    }
1 Like

hello hello…
for me everything worked very well… but I have one question regarding the Previous Button with the arrow, it always showed up like that ( Prev < ) never like that ( < Prev )

how to flip this thing?

note: If i use DrawableStart or DrawableLeft, the arrow doesn’t show up… only when I use DrawableEnd/Right that i can see it

@Saher.alsous there seems to be an issue with the attribute drawableStart for example a similar bug has been raised here.

Also it seems to be theme specific if you switch to a different theme it seems to work.

For instance in the layout preview switching to the theme AppCompat.Light.NoActionBar seemed to work for me.

However applying a theme change to your app requires an update to the theme value in your app manifest i.e. the line android:theme="@style/Theme.GeoQuiz">

Following is a sample GeoQuiz app manifest.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.bignerdranch.android.geoquiz">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.GeoQuiz">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
1 Like

check out this

    // prevButton
    prevButton.setOnClickListener {
        if (currentIndex==0) {
            currentIndex = (currentIndex + 1) % questionBank.size
            updateQuestion()
        } else {
            currentIndex = (currentIndex - 1) % questionBank.size
            updateQuestion()
        }

    }
1 Like

For me, my first guess drawableStart does not work. But drawableLeft which I did not notice until reading your post does!

I’m on the default latest API as of this date if that matters.

These API’s do seem to change pretty often I’ve discovered in the first couple chapters already :slight_smile:

1 Like

There is my solution for prevButton

private fun nextQuestion() {
        currentIndex = (currentIndex + 1) % questionBank.size
        updateQuestion()
    }
    private fun prevQuestion() {
        currentIndex = (currentIndex - 1 + questionBank.size) % questionBank.size
        updateQuestion()
    }

package com.example.csc2074_19051374_assignment

import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.*
import androidx.core.content.ContextCompat
import kotlin.Result

class QuestionActivity:AppCompatActivity(), View.OnClickListener {

private lateinit var progressBar: ProgressBar
private lateinit var progressText: TextView
private lateinit var questiontext: TextView
private lateinit var questionList: MutableList<Question>
private var selectedOptionPosition = 0
private lateinit var option1: TextView
private lateinit var option2: TextView
private lateinit var checkButton: Button
private lateinit var resetButton: Button
private lateinit var previousButton: Button
private var questionsCounter = 0
private var selectedAnswer = 0
private lateinit var currentQuestion: Question
private var answered = false
private lateinit var name:String
private var score = 0


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_question)

    progressBar = findViewById(R.id.progressBar)
    progressText = findViewById(R.id.progressText)
    questiontext = findViewById(R.id.question_text)
    checkButton = findViewById(R.id.button_submit)
    resetButton = findViewById(R.id.reset_button)
    previousButton = findViewById(R.id.previous_button)

    option1 = findViewById(R.id.option_1)
    option2 = findViewById(R.id.option_2)

    option1.setOnClickListener(this)
    option2.setOnClickListener(this)
    checkButton.setOnClickListener(this)
    resetButton.setOnClickListener{
        finish()
        startActivity(intent)
        showNextQuestion()
        Toast.makeText(this,"Current restart",Toast.LENGTH_LONG).show()
    }

    questionList = Constants.getQuestions()
    Log.d("Question Size", "${questionList.size}")

    showNextQuestion()
    if (intent.hasExtra(Constants.USER_NAME)){
        name = intent.getStringExtra(Constants.USER_NAME)!!
    }
}


private fun showNextQuestion() {


    if (questionsCounter < questionList.size) {
        checkButton.text = "Check"
        currentQuestion = questionList[questionsCounter]

        resetOptions()
        val question = questionList[questionsCounter]
        progressBar.progress = questionsCounter
        progressText.text = "${questionsCounter + 1}/${progressBar.max}"
        questiontext.text = question.question
        option1.text = question.option1
        option2.text = question.option2

    } else {
        checkButton.text = "Finish"
        Intent(this, Result::class.java).also {
            it.putExtra(Constants.USER_NAME,name)
            it.putExtra(Constants.SCORE,score)
            it.putExtra(Constants.TOTAL_QUESTIONS,questionList.size)
            startActivity(it)
        }
    }
    questionsCounter++
    answered = false

}

private fun resetOptions() {
    val options = mutableListOf<TextView>()

    options.add(option1)
    options.add(option2)

    for (option in options) {
        option.setTextColor(Color.parseColor("#7A8089"))
        option.typeface = Typeface.DEFAULT
        option.background = ContextCompat.getDrawable(this, R.drawable.question_option)
    }
}

override fun onClick(view: View?) {
    when (view?.id) {
        R.id.option_1 -> {
            selectedOption(option1, 1)
        }

        R.id.option_2 -> {
            selectedOption(option2, 2)
        }

        R.id.button_submit -> {
            if (!answered) {
                checkAnswer()
            } else {
                showNextQuestion()
            }
            selectedAnswer = 0
        }
    }
}

private fun selectedOption(textView: TextView, selectedOptionNumber: Int) {
    resetOptions()
    selectedAnswer = selectedOptionNumber
    selectedOptionPosition = selectedOptionNumber

    textView.setTextColor(Color.parseColor("#363A43"))
    textView.setTypeface(textView.typeface, Typeface.BOLD)
    textView.background = ContextCompat.getDrawable(
        this,
        R.drawable.selected_question_option
    )

}

private fun restartQuiz(){
    currentQuestion
    score = 0
    showNextQuestion()
    resetButton.isEnabled = false
}

private fun checkAnswer() {
    answered = true

    if (selectedAnswer == currentQuestion.correctAnswer) {
        score++
        highlightedAnswer(selectedAnswer)

    } else {
        when (selectedAnswer) {
            1 -> {
                option1.background = ContextCompat.getDrawable(
                    this,
                    R.drawable.wrong_question_option
                )
            }

            2 -> {
                option2.background = ContextCompat.getDrawable(
                    this,
                    R.drawable.wrong_question_option
                )

            }

        }
    }

    checkButton.text = "Next"
    showSolution()
}

private fun showSolution() {
    selectedAnswer = currentQuestion.correctAnswer
    highlightedAnswer(selectedAnswer)
    when (selectedAnswer) {
        1 -> {
            option1.background = ContextCompat.getDrawable(
                this,
                R.drawable.correct_question_option
            )
        }

        2 -> {
            option2.background = ContextCompat.getDrawable(
                this,
                R.drawable.correct_question_option
            )
        }
    }

}

private fun highlightedAnswer(answer: Int) {
    when (answer) {
        1 -> {
            option1.background = ContextCompat.getDrawable(
                this,
                R.drawable.correct_question_option
            )
        }

        2 -> {
            option2.background = ContextCompat.getDrawable(
                this,
                R.drawable.correct_question_option
            )
        }
    }

    }
}

can anyone teach me how to do the previous button function?