이번에는 저번에 만든거에 이어서 퀴즈앱을 마무리 해보려고한다!
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ic_bg"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Quiz app!"
android:textSize="25sp"
android:textStyle="bold"
android:layout_marginBottom="30dp"
android:gravity="center"
android:textColor="@color/white" />
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
app:cardCornerRadius="10dp"
android:background="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Welcome"
android:textSize="30sp"
android:textStyle="bold"
android:gravity="center"
android:textColor="#362A43" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="이름을 입력하세요"
android:layout_marginTop="16dp"
android:textSize="16sp"
android:textStyle="bold"
android:gravity="center"
android:textColor="#7A8089" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_marginTop="20dp">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Name"
android:inputType="textCapWords"
android:textColor="#362A43"
android:textColorHint="#7A8089"/>
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/btn_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@color/design_default_color_primary"
android:text="Start"
android:textColor="@color/white"
android:textSize="18sp"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
activity_main.xml
package com.example.quizapp
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 변수 초기화
val btnStart : Button = findViewById(R.id.btn_start)
val etName : EditText = findViewById(R.id.et_name)
//btn_start버튼 눌렀을때
btnStart.setOnClickListener {
//텍스트가 비어있다면 토스트메세지를 출력
if(etName.text.isEmpty()){
Toast.makeText(this,"이름을 입력해주세요", Toast.LENGTH_SHORT).show()
}else{
//텍스트가 비어있지 않다면 QuizQuestionActivity로 이동
val intent = Intent(this, QuizQuestionActivity::class.java)
//엑티비티 시작시키는 동시에, QuizQuestionActivity로 정보값을 보냄
//etName에서 입력한 사용자 이름을 보냄
intent.putExtra(Constants.USER_NAME, etName.text.toString())
startActivity(intent)
finish()
}
}
}
}
MainActivity.kt
package com.example.quizapp
//퀴즈에 들어갈 데이터클래스 생성 (데이터클래스의 속성 정하기)
data class Question(
val id : Int, //id
val question : String, //질문
val image : Int, //이미지 (int타입으로 이미지만들수있음)
val optionOne : String, //정답체크옵션1
val optionTwo : String, //정답체크옵션2
val optionThree : String, //정답체크옵션3
val optionFour : String, //정답체크옵션4
val correctAnswer : Int //정답
)
Question.kt
여기까지는 이전에 작성했던 내용이랑 똑같음
package com.example.quizapp
// 실제 들어갈 데이터값 만들기
object Constants {
// activity_result에 해당하는 정보
const val USER_NAME : String = "user_name" // username
const val TOTAL_QUESTIONS : String = "total_questions" // 전체질문의 개수
const val CORRECT_ANSWERS : String = "correct_answers" // 맞힌질문의 개수
//이 함수를 실행시켰을때 Question에 담긴 데이터들을 전부 가져오도록
fun getQuestions() : ArrayList<Question>{
//questionsList에 각각의 질문에 해당하는 값이 담겨있음
val questionsList = ArrayList<Question>()
// que1
val que1 = Question(
1, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_argentina,
"Argentina", "Australia",
"Armenia", "Austria",
1
)
questionsList.add(que1)
//que2
val que2 = Question(
2, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_australia,
"Angola", "Austria",
"Australia", "Armenia",
3
)
questionsList.add(que2)
//que3
val que3 = Question(
3, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_belgium,
"Bahamas", "Belgium",
"Barbados", "Belize",
2
)
questionsList.add(que3)
//que4
val que4 = Question(
4, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_denmark,
"Dominica", "Egypt",
"Denmark", "Ethiopia",
3
)
questionsList.add(que4)
//que5
val que5 = Question(
5, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_fiji,
"Gabon", "France",
"Fiji", "Finland",
3
)
questionsList.add(que5)
//que6
val que6 = Question(
6, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_germany,
"Germany", "Georgia",
"Greece", "none of these",
1
)
questionsList.add(que6)
//que7
val que7 = Question(
7, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_india,
"Ireland", "Iran",
"Hungary", "India",
4
)
questionsList.add(que7)
//que8
val que8 = Question(
8, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_kuwait,
"Kuwait", "Jordan",
"Sudan", "Palestine",
1
)
questionsList.add(que8)
//que9
val que9 = Question(
9, "이 국기는 어느나라의 국기일까요?",
R.drawable.ic_flag_of_new_zealand,
"Australia", "New Zealand",
"Tuvalu", "United States of America",
2
)
questionsList.add(que9)
return questionsList
}
}
Constants.kt
ResultActivity를 새로 만들어줬기때문에 위에 3줄을 추가해서 username, 전체질문의 개수,맞힌질문의 개수에 대한 정보를 가져온다
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:context=".QuizQuestionActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tv_question"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center"
android:textColor="#363A43"
android:textSize="22sp"
tools:text="이 국기는 어느나라의 국기일까요?" />
<ImageView
android:id="@+id/iv_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:contentDescription="Quiz Image"
tools:src="@drawable/ic_flag_of_germany"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="0dp"
style="?android:attr/progressBarStyleHorizontal"
android:layout_height="wrap_content"
android:layout_weight="1"
android:max="9"
android:indeterminate="false"
android:minHeight="50dp"
android:progress="5"/>
<TextView
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:textSize="14sp"
tools:text="0/9"/>
</LinearLayout>
<TextView
android:id="@+id/tv_option_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/option"
android:gravity="center"
android:padding="15dp"
android:textColor="#7A8089"
android:textSize="18sp"
tools:text="Apple"/>
<TextView
android:id="@+id/tv_option_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/option"
android:gravity="center"
android:padding="15dp"
android:textColor="#7A8089"
android:textSize="18sp"
tools:text="Apple"/>
<TextView
android:id="@+id/tv_option_three"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/option"
android:gravity="center"
android:padding="15dp"
android:textColor="#7A8089"
android:textSize="18sp"
tools:text="Apple"/>
<TextView
android:id="@+id/tv_option_four"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@drawable/option"
android:gravity="center"
android:padding="15dp"
android:textColor="#7A8089"
android:textSize="18sp"
tools:text="Apple"/>
<Button
android:id="@+id/btn_submit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="@color/design_default_color_primary"
android:text="제출하기"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"/>
</LinearLayout>
</ScrollView>
activity_quiz_question.xml
이부분도 이전에 작성했던 코드랑 똑같다
package com.example.quizapp
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.view.View.OnClickListener
import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.ContextCompat
class QuizQuestionActivity : AppCompatActivity(), OnClickListener{
//현재위치를 정함
private var mCurrentPosition : Int = 1
//질문의 ArrayList?
private var mQuestionsList : ArrayList<Question>? = null
//어떤 옵션을 선택했는지 확인하기위해
private var mSelectedOptionPosition : Int = 0
private var mUserName :String? = null //사용자이름
private var mCorrectAnswers : Int = 0 //정답개수
private var tvQuestion : TextView? = null
private var ivImage : ImageView? = null
private var progressBar : ProgressBar? = null
private var tvProgress : TextView? = null
private var tvOptionOne : TextView? = null
private var tvOptionTwo : TextView? = null
private var tvOptionThree: TextView? = null
private var tvOptionFour : TextView? = null
private var btnSubmit : Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz_question)
tvQuestion = findViewById(R.id.tv_question)
ivImage = findViewById(R.id.iv_image)
progressBar = findViewById(R.id.progressBar)
tvProgress = findViewById(R.id.tv_progress)
tvOptionOne = findViewById(R.id.tv_option_one)
tvOptionTwo = findViewById(R.id.tv_option_two)
tvOptionThree = findViewById(R.id.tv_option_three)
tvOptionFour = findViewById(R.id.tv_option_four)
btnSubmit = findViewById(R.id.btn_submit)
tvOptionOne?.setOnClickListener(this)
tvOptionTwo?.setOnClickListener(this)
tvOptionThree?.setOnClickListener(this)
tvOptionFour?.setOnClickListener(this)
btnSubmit?.setOnClickListener(this)
// mQuestionsList 로드
mQuestionsList = Constants.getQuestions()
setQuestion()
//추가!!
// MainActivity에서 보냈던 USER_NAME을 받아옴
mUserName = intent.getStringExtra(Constants.USER_NAME)
}
private fun setQuestion() {
// Constants.kt에 적은 데이터값이 나오도록 연결
// index 1번에 해당하는 질문부터 시작하고싶기때문에 1로 설정
// mCurrentPosition = 1
val question: Question = mQuestionsList!![mCurrentPosition - 1]
//tvQuestion 들어갈값 표시
tvQuestion?.text = question.question
//ivImage 들어갈값 표시 (image를 int값으로 지정했기때문에 setImageResource로 표시)
ivImage?.setImageResource(question.image)
//progressBar 들어갈값 표시
progressBar?.progress = mCurrentPosition
// tvProgress 들어갈값 표시
tvProgress?.text = "$mCurrentPosition/${progressBar?.max}"
//tvOption 4개에 들어갈값 표시
tvOptionOne?.text = question.optionOne
tvOptionTwo?.text = question.optionTwo
tvOptionThree?.text = question.optionThree
tvOptionFour?.text = question.optionFour
// 마지막화면버튼에는 finish버튼 표시
// 현재위치랑 mQuestionsList의 사이즈가 같다면 if문 실행
// 현재위치가 마지막이라면 if문 실행
if (mCurrentPosition == mQuestionsList!!.size){
btnSubmit?.text = "FINISH"
}else{
btnSubmit?.text = "제출하기"
}
// 옵션값 리셋(기본값으로)
defaultOptionsView()
}
// 옵션버튼 누르기전 기본값 (defaultOptionsView변수 생성)
private fun defaultOptionsView(){
//옵션버튼의 TextView
val options = ArrayList<TextView>()
tvOptionOne?.let {
options.add(0,it) //index=0, it=실제 optionOne의 텍스트뷰
}
tvOptionTwo?.let {
options.add(1,it) //index=1, it=실제 tvOptionTwo의 텍스트뷰
}
tvOptionThree?.let {
options.add(2,it) //index=1, it=실제 tvOptionThree의 텍스트뷰
}
tvOptionFour?.let {
options.add(3,it) //index=1, it=실제 tvOptionFour의 텍스트뷰
}
// for 반복문으로 option안의 option을 확인
for(option in options){
//options(옵션버튼의 TextView)의 색상이 바뀌도록
option.setTextColor(Color.parseColor("#7A8089"))
// Typeface를 DEFAULT값으로 설정해서 옵션 선택했을때 바뀌도록
option.typeface = Typeface.DEFAULT
//배경
option.background = ContextCompat.getDrawable(
this, R.drawable.option
)
}
}
//옵션을 눌렀을때 보여주는값
private fun selectedOptionView(tv:TextView, selectedOptionNum : Int){
//defaultOptionsView를 불러와서 모든버튼을 기본으로 돌아가게함
defaultOptionsView()
mSelectedOptionPosition = selectedOptionNum
//텍스트뷰 색상,볼드체,배경 설정
tv.setTextColor(Color.parseColor("#363A43"))
tv.setTypeface(tv.typeface, Typeface.BOLD)
tv.background = ContextCompat.getDrawable(
this, R.drawable.selected_option
)
}
override fun onClick(v: View?) {
//textview를 눌렀을때
when(v?.id){
//tv_option_one를 눌렀을때 실행할옵션
R.id.tv_option_one -> {
tvOptionOne?.let {
selectedOptionView(it,1)
}
}
R.id.tv_option_two -> {
tvOptionTwo?.let {
selectedOptionView(it,2)
}
}
R.id.tv_option_three -> {
tvOptionThree?.let {
selectedOptionView(it,3)
}
}
R.id.tv_option_four -> {
tvOptionFour?.let {
selectedOptionView(it,4)
}
}
// btn_submit을 눌렀을때 실행할옵션
R.id.btn_submit -> {
if (mSelectedOptionPosition == 0){ //선택한 옵션의 위치를 기본값인 0으로 두고 (현재위치)
mCurrentPosition++ //mCurrentPosition++ 으로 현재위치에 1을 더해서 다음질문으로 넘어가게
//다음질문으로
when{
mCurrentPosition <= mQuestionsList!!.size -> {
setQuestion()
}
else -> { // 다음질문이 없을때 (마지막 질문일때)
val intent = Intent(this, ResultActivity::class.java)
// putExtra를 사용해서 ResultActivity로 USER_NAME, CORRECT_ANSWERS, TOTAL_QUESTIONS 값들을 보냄(이름,맞힌질문의개수,전체질문의개수)
intent.putExtra(Constants.USER_NAME, mUserName)
intent.putExtra(Constants.CORRECT_ANSWERS, mCorrectAnswers)
intent.putExtra(Constants.TOTAL_QUESTIONS, mQuestionsList?.size)
startActivity(intent)
finish()
}
}
}else{
val question = mQuestionsList?.get(mCurrentPosition -1)
//정답을 선택했는지 아닌지 if문을 통해 확인
//정답이 아닌걸 선택했다면
if(question!!.correctAnswer != mSelectedOptionPosition){
// if문으로 선택한 옵션에 빨간배경표시
answerView(mSelectedOptionPosition, R.drawable.wrong_option)
// 정답을 선택했다면, 정답개수 증가
}else{
mCorrectAnswers++
}
// 동시에 선택한 옵션을 초록색으로 바꿈
// 정답은 정답을 선택한경우든지 오답을 선택한경우든지 무조건 표시하는거기때문에 else문 나와서 작성
answerView(question.correctAnswer, R.drawable.correct_option)
//mCurrentPosition이 질문의개수와 같다면(마지막질문이라면)
if(mCurrentPosition == mQuestionsList!!.size){
btnSubmit?.text = "FINISH"
}else{ //마지막 질문이 아니라면
btnSubmit?.text = "다음질문"
}
//선택한 옵션의 위치를 0으로 돌아가게 (이걸 안하면 지금 선택한 옵션이 그대로 남아서 에러뜸)
mSelectedOptionPosition = 0
}
}
}
}
// 옵션 눌렀을때 정답값
private fun answerView(answer:Int, drawableView: Int){
//정답이 1번이면 1로,2번이면 2로,,,
when(answer){
1 -> {
tvOptionOne?.background = ContextCompat.getDrawable(
this, drawableView
)
}
2 -> {
tvOptionTwo?.background = ContextCompat.getDrawable(
this, drawableView
)
}
3 -> {
tvOptionThree?.background = ContextCompat.getDrawable(
this, drawableView
)
}
4 -> {
tvOptionFour?.background = ContextCompat.getDrawable(
this, drawableView
)
}
}
}
}
QuizQuestionActivity.kt
여기는 추가된부분이 많은데 btn_submit 버튼을 눌렀을때, 옵션 눌렀을때의 동작을 추가했다
즉, 제출하기버튼을 눌렀을때 다음질문으로 넘어가도록했고
정답을 선택했는지에 따라서 초록색,빨간색으로 버튼색이 바뀌게했다
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/ic_bg"
android:gravity="center_horizontal"
android:padding="20dp"
tools:context=".ResultActivity">
<TextView
android:id="@+id/tv_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:text="결과"
android:textColor="@color/white"
android:textSize="25sp"
android:textStyle="bold"/>
<ImageView
android:id="@+id/iv_trophy"
android:layout_width="120dp"
android:layout_height="120dp"
android:contentDescription="image"
android:layout_marginTop="100dp"
android:src="@drawable/ic_trophy"/>
<TextView
android:id="@+id/tv_congratulations"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:text="Congratulations!"
android:textColor="@color/white"
android:textSize="25sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="25dp"
android:textColor="@color/white"
android:textSize="22sp"
android:textStyle="bold"
tools:text="Username"/>
<TextView
android:id="@+id/tv_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textColor="@color/material_dynamic_secondary10"
android:textSize="20sp"
tools:text="점수는 9점만점중에 8점입니다"/>
<Button
android:id="@+id/btn_finish"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:backgroundTint="@color/white"
android:text="FINISH"
android:textColor="@color/design_default_color_primary"
android:textSize="18sp"
android:textStyle="bold"/>
</LinearLayout>
activity_result.xml
그리고 마지막에 질문이 다 끝났을때 Finish버튼을 누르면 이동하는 화면을 만들었다
이 앱의 마지막화면이다
사용자의 이름, 맞춘개수를 표시해준다
package com.example.quizapp
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
class ResultActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_result)
val tvName : TextView = findViewById(R.id.tv_name)
val tvScore : TextView = findViewById(R.id.tv_score)
val btnFinish : Button = findViewById(R.id.btn_finish)
// tv_name에 텍스트표시
tvName.text = intent.getStringExtra(Constants.USER_NAME)
val totalQuestions = intent.getIntExtra(Constants.TOTAL_QUESTIONS,0) //전체질문의 개수
val correctAnswers = intent.getIntExtra(Constants.CORRECT_ANSWERS,0) //맞힌질문의 개수
// tv_score에 텍스트표시
tvScore.text = "점수는 $totalQuestions 점만점중에 $correctAnswers 점입니다"
// finish버튼 누르면 MainActivity로 넘어가도록
btnFinish.setOnClickListener{
startActivity(Intent(this, MainActivity::class.java))
}
}
}
ResultActivity.kt
QuizQuestionActivity.kt에서 putExtra로 ResultActivity에 이름,맞힌질문의개수,전체질문의 개수에 관련된 값을 넘겨주었었는데
이걸 ResultActivity에서 getExtra를 사용해 받아와서 정보값을 표시해준다
따라서 이름과 내가 맞춘점수가 표시되는걸 볼수있다
그리고 finish버튼을 누르면 처음화면인 MainActivity로 이동하도록했다
'Android Project' 카테고리의 다른 글
[Android/Kotlin] FLO앱 클론코딩(2) (0) | 2024.01.05 |
---|---|
[Android/Kotlin] FLO앱 클론코딩(1) (0) | 2024.01.05 |
[Android/Kotlin] 드로잉앱(1) (0) | 2023.12.13 |
[Android/Kotlin] 퀴즈앱(1) (0) | 2023.12.10 |
[Android/Kotlin] 계산기앱 (0) | 2023.12.10 |