카테고리 없음

9주차 3일 이모저모

시계속세상은아직돌아가는중 2023. 9. 6. 21:24

1. cointoss minigame

 

package com.example.nbcamp_teamproject_call.minigame

import android.content.Context
import android.content.Intent
import android.media.MediaPlayer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.ImageView
import android.widget.Toast
import com.example.nbcamp_teamproject_call.R
import com.example.nbcamp_teamproject_call.databinding.CoinTossActivityBinding
import java.util.Timer
import kotlin.concurrent.schedule

class CoinTossActivity : AppCompatActivity() {

    companion object {
        fun getIntentCoin(context: Context) = Intent(context, CoinTossActivity::class.java)

    }

    private lateinit var binding: CoinTossActivityBinding
    private var state0Count = 0
    private var state1Count = 0
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = CoinTossActivityBinding.inflate(layoutInflater)
        setContentView(binding.root)

        initView()
    }

    private fun initView() = with(binding) {

        var case: Int = 0

        coinTossBackBtn.setOnClickListener {
            finish()
        }

        val coinImageViews = arrayOf(
            coinTossImgCoin1,
            coinTossImgCoin2,
            coinTossImgCoin3,
            coinTossImgCoin4,
            coinTossImgCoin5,
            coinTossImgCoin6
        )

        //백버튼
        coinTossImgBackArrow.setOnClickListener {
            finish()
        }

        //하단 버튼 제어

        tossBtn.setOnClickListener {
            when (case) {
                0 -> {
                    var soundPlayer: MediaPlayer? =
                        MediaPlayer.create(this@CoinTossActivity, R.raw.coin_effect)
                    soundPlayer?.start()

                    coinImageViews.forEach { coinToss(it) }

                    Timer().schedule(2500) {
                        runOnUiThread {
                            coinTossTvIsFront.visibility = View.VISIBLE
                            coinTossEtIsFront.visibility = View.VISIBLE
                            coinTossEtIsBack.visibility = View.VISIBLE
                            coinTossTvIsBack.visibility = View.VISIBLE

                            tossBtn.text = "Check the answer"
                            case = 1
                        }
                    }
                }

                1 -> {
                    coinImageViews.forEach { it.visibility = View.VISIBLE }

                    val answerFront = coinTossEtIsFront.text.toString() ?: "0"
                    val answerBack = coinTossEtIsBack.text.toString() ?: "0"

                    if (answerFront == state0Count.toString() && answerBack == state1Count.toString()) Toast.makeText(
                        this@CoinTossActivity,
                        "정답입니다",
                        Toast.LENGTH_SHORT
                    ).show()
                    else Toast.makeText(
                        this@CoinTossActivity,
                        "오답입니다.",
                        Toast.LENGTH_SHORT
                    ).show()

                    tossBtn.text = "Reset"
                    case = 2
                }

                2 -> {
                    coinTossTvIsFront.visibility = View.INVISIBLE
                    coinTossEtIsFront.visibility = View.INVISIBLE
                    coinTossEtIsFront.text = null
                    coinTossEtIsBack.visibility = View.INVISIBLE
                    coinTossEtIsBack.text = null
                    coinTossTvIsBack.visibility = View.INVISIBLE

                    state0Count = 0
                    state1Count = 0

                    coinImageViews.forEach { it.setImageResource(R.drawable.coin_front) }

                    tossBtn.text = "Coin Toss"
                    case = 0
                }
            }

        }

    }

    private fun coinToss(view: ImageView) {
        var state = 1

        var animaition: Animation =
            AnimationUtils.loadAnimation(this@CoinTossActivity, R.anim.coin_effect)
        view.startAnimation(animaition)

        Timer().schedule(2600) {
            runOnUiThread {
                view.visibility = View.INVISIBLE

                state = (0..1).random()

                when (state) {
                    0 -> {
                        view.setImageResource(R.drawable.coin_front)
                        state0Count++
                    }

                    1 -> {
                        view.setImageResource(R.drawable.coin_back)
                        state1Count++
                    }
                }
            }

        }
    }
}

여기서 처음 써본 것

runOnUiThread

이 것은 뷰에 직접적으로 딜레이를 주게되면 오류가 나게 되므로 주게 되는 UiThread다

이 부분을 잘 몰라서 앱이 죽는 것을 여러번 반복했다.

 

여기서 특이한점은 fun coinToss에서 Thread를 안줬는데도 작동을 하다가 중간에 죽었다는 것 이다.

그 이유는 튜터님하고 함께 원인규명을 해봤으나, 알 수 없었다.

 

도대체 왜 작동하면 안되는 로직이 작동했었을까?

 

2.viewtype 분기

package com.example.nbcamp_teamproject_call.contact

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.nbcamp_teamproject_call.databinding.ContactItem2Binding
import com.example.nbcamp_teamproject_call.databinding.ContactItemBinding
import com.example.nbcamp_teamproject_call.model.UserDB
import com.example.nbcamp_teamproject_call.model.UserModel

class ContactAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    companion object {
        const val VIEW_TYPE_1 = 1
        const val ViEW_TYPE_2 = 2
    }

    private var list = mutableListOf<UserModel>()
    private var viewType = VIEW_TYPE_1
    fun setContactList(contactList: List<UserModel>) {
        if (contactList.isEmpty()) return
        list.addAll(contactList)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            VIEW_TYPE_1 -> {
                ContactViewHolder(
                    ContactItemBinding.inflate(LayoutInflater.from(parent.context))
                )
            }
            else -> {
                Type2ViewHolder(
                    ContactItem2Binding.inflate(LayoutInflater.from(parent.context))
                )
            }
        }
    }

    override fun getItemCount(): Int {
        return UserDB.getInstance().size
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val item = list[position]
      when(viewType){
          VIEW_TYPE_1 ->{
              if (holder is ContactViewHolder) {
                  holder.onBind(item)
                  holder.setIsRecyclable(false)
              }
          }
          else ->{
              if (holder is Type2ViewHolder) {
                  holder.onBind(item)
                  holder.setIsRecyclable(false)
              }
          }
      }
    }



}

두 개의 뷰 분기를 위한 const val를 사용하여 현재 type상태를 판단할 수 있는 변수를 전역으로 선언하였다.

 

따라서 각 타입에 맞는 홀더 두 개를 따로 class를 만들어 생성한 다음에 넣어주었다.

 

다만 현재 문제가 있다.

onBindViewHolder

부분의 홀더가 제대로 작동하지 않는 이슈가 있다.

이에 대한 것을 고치는 중이다.

 

참고 블로그

https://velog.io/@devyang97/Android-RecyclerView-ViewType%EC%9D%84-%EC%A7%80%EC%A0%95%ED%95%98%EC%97%AC-%EC%84%9C%EB%A1%9C-%EB%8B%A4%EB%A5%B8-View-%EB%B3%B4%EC%97%AC%EC%A3%BC%EA%B8%B0