Skip to content

Never-Die-Zombieroid โ˜„๐Ÿง›โ€โ™€๏ธ

Notifications You must be signed in to change notification settings

Apophis-AppJam/ApophisAndroid

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ApophisAndroid : Never-Die-Zombieroid ๐ŸŒ ๐Ÿง›โ€โ™€๏ธ


ํ”„๋กœํ•„

SOPT 27๊ธฐ 17th APP-JAM : Apophis ๐ŸŒ 


๐Ÿ“Œ Part-meeting


๋งค์ผ ์ €๋… 7์‹œ 30๋ถ„

https://www.notion.so/b562e3c34a9e4641b5025506546260a0


๐ŸŽจ Kanban-board


https://github.com/Apophis-AppJam/ApophisAndroid/projects/1


๐Ÿ”ง Tools


  • Android Studio
  • Zeplin
  • Figma

โœŒ Communication tools


  • Notion
  • Slack
  • Gather
  • Zoom

๐Ÿงฉ Branch naming


  • feature : ๊ธฐ๋Šฅ ๊ฐœ๋ฐœํ•˜๋Š” ๋ธŒ๋žœ์น˜

    feature/[์ด์Šˆ๋ฒˆํ˜ธ] _ [๊ธฐ๋Šฅ] _ [layout/inflate]


๐Ÿ’ฌ Commit message


ex) [Add] ํ™ˆ ํ™”๋ฉด Layout ์ž‘์„ฑ ์™„๋ฃŒ

    1. ์„ค๋ช…1
    2. ์„ค๋ช… 2

[Add] ๊ธฐ๋Šฅ์ถ”๊ฐ€

[Delete] ์‚ญ์ œ

[Update] ๊ธฐ๋Šฅ์ˆ˜์ •

[Fix] ๋ฒ„๊ทธ์ˆ˜์ •

[Docs] ๋ฌธ์„œ์ •๋ฆฌ

[Chore] ์žก์ผ


๐Ÿ”— Dependency


/* retrofit */
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-gson:2.7.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.1'

/* gson */
implementation 'com.google.code.gson:gson:2.8.6'

/* glide */
implementation "com.github.bumptech.glide:glide:4.10.0"
kapt "com.github.bumptech.glide:compiler:4.10.0"

//lottie
implementation 'com.airbnb.android:lottie:3.4.0'

/* recyclerview */
implementation "androidx.recyclerview:recyclerview:1.2.0-alpha02"

/* kakao */
implementation 'com.kakao.sdk:usermgmt:1.28.0'

implementation platform('com.google.firebase:firebase-bom:26.2.0')
implementation 'com.google.firebase:firebase-analytics-ktx'
implementation 'com.google.firebase:firebase-auth:19.1.0'
implementation 'com.google.android.gms:play-services-auth:17.0.0'
compileOnly 'com.google.android.wearable:wearable:2.8.1'

/* camera */
def camerax_version = "1.0.0-beta07"
implementation "androidx.camera:camera-camera2:$camerax_version"
implementation "androidx.camera:camera-lifecycle:$camerax_version"
implementation "androidx.camera:camera-view:1.0.0-alpha14"

๐Ÿงฑ Project structure


๐ŸŒ apophis_android
 โ”ฃ ๐Ÿ“‚data
 โ”ƒ โ”ฃ ๐Ÿ“‚entity
 โ”ƒ โ”— ๐Ÿ“‚remote
 โ”ƒ    โ”ฃ ๐Ÿ“‚request
 โ”ƒ    โ”— ๐Ÿ“‚response
 โ”— ๐Ÿ“‚ui
   โ”ฃ ๐Ÿ“‚firstDay
   โ”ƒ โ”— ๐Ÿ“‚adapter
   โ”ฃ ๐Ÿ“‚login
   โ”ฃ ๐Ÿ“‚main
   โ”ƒ  โ”ฃ ๐Ÿ“‚letter
   โ”ƒ ๐Ÿ“‚onboarding
   โ”ƒ  โ”— ๐Ÿ“‚adapter
   โ”ฃ ๐Ÿ“‚secondDay
   โ”ƒ โ”ฃ ๐Ÿ“‚adapter
   โ”ƒ โ”ฃ ๐Ÿ“‚findMe
   โ”ƒ โ”ฃ ๐Ÿ“‚time
   โ”ƒ โ”— ๐Ÿ“‚value
   โ”ฃ ๐Ÿ“‚seventhDay
   โ”ƒ โ”ฃ ๐Ÿ“‚adapter
   โ”ƒ โ”— ๐Ÿ“‚tarot
   โ”ฃ ๐Ÿ“‚sixthDay
   โ”ƒ โ”— ๐Ÿ“‚adapter
   โ”— ๐Ÿ“„ChipFactory.kt

  


๐Ÿ”ง Tech Stack


  1. ์นด๋ฉ”๋ผ ์ด๋ฏธ์ง€ ์บก์ฒ˜
 imageCapture.takePicture(
            ContextCompat.getMainExecutor(this),
            object : ImageCapture.OnImageCapturedCallback() {
                @SuppressLint("UnsafeExperimentalUsageError")
                override fun onCaptureSuccess(imageProxy: ImageProxy) {
                    imageProxy.image?.let {
                        val rotationDegrees = imageProxy.imageInfo.rotationDegrees
                        previewPicture = it.toBitmap(rotationDegrees)

                        iv_camera_capture.setImageBitmap(previewPicture)
                        super.onCaptureSuccess(imageProxy)
                        previewMode()
                    }
                }

                override fun onError(exception: ImageCaptureException) {
                    val msg = "Photo capture failed: ${exception.message}"
                }
            })

imageProxy๋กœ ๋ฐ›์•„์„œ ์›ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๋ณ€ํ˜•ํ•ด์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ


  1. ๋‚˜์นจ๋ฐ˜ ์„ผ์„œ ๋ฉ”์†Œ๋“œ
override fun onSensorChanged(event: SensorEvent) {
        if (event.sensor === accelerometer) {
            lowPass(event.values, lastAccelerometer)
            lastAccelerometerSet = true
        } else if (event.sensor === magnetometer) {
            lowPass(event.values, lastMagnetometer)
            lastMagnetometerSet = true
        }

        if (lastAccelerometerSet && lastMagnetometerSet) {
            val r = FloatArray(9)
            if (SensorManager.getRotationMatrix(r, null, lastAccelerometer, lastMagnetometer)) {
                val orientation = FloatArray(3)
                SensorManager.getOrientation(r, orientation)
                val degree = (Math.toDegrees(orientation[0].toDouble()) + 360).toFloat() % 360

                var rotateAnimation = RotateAnimation(
                    currentDegree,
                    -degree,
                    Animation.RELATIVE_TO_SELF, 0.5f,
                    Animation.RELATIVE_TO_SELF, 0.5f)
                rotateAnimation.duration = 200
                rotateAnimation.fillAfter = true

                image.startAnimation(rotateAnimation)
                currentDegree = -degree

                if (degree > 80 && degree < 100) {
                    Timer().schedule(1500) {
                        runOnUiThread {
                            iv_compass_arrow.setImageResource(R.drawable.img_compass_arrow_bold)
                            sensorManager.unregisterListener(this@CompassActivity, accelerometer)
                            sensorManager.unregisterListener(this@CompassActivity, magnetometer)
                            rotateAnimation = RotateAnimation(
                                -90.toFloat(), (-90).toFloat(), Animation.RELATIVE_TO_SELF,
                                0.5f, Animation.RELATIVE_TO_SELF, 0.5f
                            )
                            rotateAnimation.duration = 210
                            rotateAnimation.fillAfter = true
                            currentDegree = -degree
                            iv_compass.startAnimation(rotateAnimation)
                            Thread.currentThread().interrupt()
                            Timer().schedule(1500){
                                finish()
                            }
                        }
                    }
                } else {
                    iv_compass.setImageResource(R.drawable.img_compass)
                }
            }
        }
    }

๊ฐ€์†๋„ ์„ผ์„œ(TYPE_ACCELEROMETER), ์ž๊ธฐ์žฅ ์„ผ์„œ(TYPE_ACCELEROMETER)๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฐ’์„ ์ง€์†์ ์œผ๋กœ ๋ฐ›์•„์™€ ๋ฐฉํ–ฅ์„ ์ธ์‹ํ•˜๊ณ  ์„ผ์„œ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋ฆฌ์Šค๋„ˆ ์˜ค๋ธŒ์ ํŠธ์˜ onSensorChanged() ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋จ


๐ŸŽ‰ Core Function


  1. ์ผ์ฐจ๋ณ„ ์ฑ„ํŒ…

ย 


class SecondDayChatActivity : AppCompatActivity() {
    private lateinit var chatAdapter: SecondDayChatAdapter
    private val apophisService = ApophisService
    private val jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWR4Ijo2LCJpYXQiOjE2MTAxNjM5NjIsImV4cCI6MTYxMDc2ODc2MiwiaXNzIjoiYXBvcGhpcyJ9.gM5avYDIhGybMsXqlvaWwqJCsTfkAjo1lYD2tvxZAdw"
    private var chatDetailsIdx = 23 // 2์ผ์ฐจ ์‹œ์ž‘ ์ธ๋ฑ์Šค 23
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second_day_chat)
        initRcv()
        getAponymousChatFromServer(jwt, chatDetailsIdx)
        btn_second_back.setOnClickListener { onBackPressed() }
        constraintLayout_second.setOnClickListener { hideKeyboard() }
        et_second_chat_message.addTextChangedListener(object: TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                btn_chat_send.setImageResource(R.drawable.btn_send_act)
            }
            override fun afterTextChanged(s: Editable?) {}
        })
        /* chip click listener ์žฌ์ •์˜ */
        chatAdapter.setOnItemClickListener(object : SecondDayChatAdapter.OnItemClickListener {
            override fun onItemClick(data: String) {
                // override fun onItemClick(data: MutableList<String>) {
                et_second_chat_message.setText(data)
                et_second_chat_message.setTextColor(Color.parseColor("#FFFFFF"))
                btn_chat_send.setImageResource(R.drawable.btn_send_act)
                /*for (i in dataList.indices) {
                    et_second_chat_message.setText(dataList[i])
                    et_second_chat_message.setTextColor(Color.parseColor("#FFFFFF"))
                    btn_chat_send.setImageResource(R.drawable.btn_send_act)
                }*/
            }
        })
    }
    private fun initRcv() {
        chatAdapter = SecondDayChatAdapter(this)
        rcv_second_chat.adapter = chatAdapter
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == SecondDayChatAdapter.TIMER_ACTIVITY_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                val text = data?.getStringExtra("text")
                et_second_chat_message.setText(text)
            }
        }
    }
    private fun getAponymousChatFromServer(jwt: String, chatDetailsIdx: Int) {
        apophisService.getInstance()
            .requestAponymousChat(
                jwt = jwt,
                chatDetailsIdx = chatDetailsIdx
            ).enqueue(object : Callback<BaseResponse<AponymousChatResponse>> {
                override fun onFailure(
                    call: Call<BaseResponse<AponymousChatResponse>>,
                    t: Throwable
                ) { //ํ†ต์‹  ์‹คํŒจ
                    Log.d("fail", t.message)
                }
                override fun onResponse(
                    call: Call<BaseResponse<AponymousChatResponse>>,
                    response: Response<BaseResponse<AponymousChatResponse>>
                ) {
                    //ํ†ต์‹  ์„ฑ๊ณต
                    if (response.isSuccessful) {
                        if (response.body()!!.success) {
                            var tag: Int
                            for (i in response.body()!!.data.chat.indices) {
                                tag = 0
                                val nextAction = response.body()!!.data.chat[i].nextAction
                                if (nextAction == "์ฑ„ํŒ… ์ด๋ฏธ์ง€") {
                                    tag = 1
                                } else if (nextAction == "๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ด๋ฏธ์ง€ - ๋ˆˆ๊ธธ ๋ทฐ"){
                                    snowBackground()
                                } else if(nextAction == "์Œ์„ฑ์†ก์ถœ1"){
                                    tag = 2
                                }
                                val aponymousChatData = OurUserChat(mutableListOf(response.body()!!.data.chat[i].text), tag)
                                chatAdapter.addChat(aponymousChatData)
                            }
                            val replyType = response.body()!!.data.postInfo.replyType
                            tag = if (replyType == "๋‹จ์ผ ๋ณด๊ธฐ ์„ ํƒ" || replyType == "๋‹ค์ค‘ ๋ณด๊ธฐ ์„ ํƒ" || replyType == "์นดํ…Œ๊ณ ๋ฆฌ ์„ ํƒ") { //chip_choice
                                4
                            } else if (replyType == "๋‹จ๋‹ตํ˜• ํ…์ŠคํŠธ ์ž…๋ ฅ") { //short answer
                                5
                            } else if (replyType == "๊ธฐ๋Šฅ ์•ก์…˜ ๋ฒ„ํŠผ - ์‹œ๊ฐ„๋Œ€ ์„ค์ •") { //timer
                                6
                            } else if (replyType == "๊ธฐ๋Šฅ ์•ก์…˜ ๋ฒ„ํŠผ - ๋‘๊ฐœ์˜ ๋‚˜ ") { //find_me
                                7
                            } else if (replyType == "๊ธฐ๋Šฅ ์•ก์…˜ ๋ฒ„ํŠผ - ๊ฐ€์น˜ ์„ ํƒ") { //value
                                8
                            } else if(replyType == "์žฅ๋ฌธํ˜• ํ…์ŠคํŠธ ์ž…๋ ฅ") { // long answer
                                9
                            } else if (replyType == "์ผ์ฐจ ์ข…๋ฃŒ (reply ์—†์Œ)") { //end
                                10
                            } else {
                                3 //chat_user
                            }
                            when (tag) {
                                0, 1, 3, 4 -> {
                                    getChoiceChatFromServer(jwt, chatDetailsIdx, tag)
                                    btn_chat_send.setOnClickListener {
                                        chatAdapter.removeChat()
                                        val userChoice = et_second_chat_message.text.toString()
                                        val chat = OurUserChat(mutableListOf(userChoice), 3)
                                        chatAdapter.addChat(chat)
                                        et_second_chat_message.setText("")
                                        postReplyOneToServer(jwt, chatDetailsIdx, 1, userChoice)
                                    }
                                }
                                5 -> { //short answer
                                    getChoiceChatFromServer(jwt, chatDetailsIdx, tag)
                                    btn_chat_send.setOnClickListener(null)
                                    chatAdapter.setCallbackListener(object : SecondDayChatAdapter.CallbackListener{
                                        override fun callBack(inputTextList: MutableList<String>) {
                                            postReplyFourToServer(jwt, chatDetailsIdx, 4, inputTextList)
                                        }
                                    })
                                }
                                9 -> { //long answer
                                    btn_chat_send.setOnClickListener {
                                        val userChoice = et_second_chat_message.text.toString()
                                        val chat = OurUserChat(mutableListOf(userChoice), 3)
                                        chatAdapter.addChat(chat)
                                        et_second_chat_message.setText("")
                                        postReplyOneToServer(jwt, chatDetailsIdx, 1, userChoice)
                                    }
                                }
                                10 -> {
                                    val user = ""
                                    val chat = OurUserChat(mutableListOf(user), 10)
                                    chatAdapter.addChat(chat)
                                    btn_chat_send.setOnClickListener(null)
                                }
                                else -> {
                                    getChoiceChatFromServer(jwt, chatDetailsIdx, tag)
                                    btn_chat_send.setOnClickListener {
                                        chatAdapter.removeChat()
                                        val userChoice = et_second_chat_message.text.toString()
                                        val chat = OurUserChat(mutableListOf(userChoice), 3)
                                        chatAdapter.addChat(chat)
                                        et_second_chat_message.setText("")
                                        postReplyOneToServer(jwt, chatDetailsIdx, 1, userChoice)
                                    }
                                }
                            }
                        }
                    }
                }
            })
    }
    private fun getChoiceChatFromServer(jwt: String, chatDetailsIdx: Int, tag: Int) {
        apophisService.getInstance()
            .requestChoiceChat(
                jwt = jwt,
                chatDetailsIdx = chatDetailsIdx
            ).enqueue(object : Callback<BaseResponse<ChoiceChatResponse>> {
                override fun onFailure(
                    call: Call<BaseResponse<ChoiceChatResponse>>,
                    t: Throwable
                ) { //ํ†ต์‹  ์‹คํŒจ
                    Log.d("fail", t.message)
                }
                override fun onResponse(
                    call: Call<BaseResponse<ChoiceChatResponse>>,
                    response: Response<BaseResponse<ChoiceChatResponse>>
                ) {
                    //ํ†ต์‹  ์„ฑ๊ณต
                    if (response.isSuccessful) {
                        if (response.body()!!.success) {
                            val replyNum = response.body()!!.data.replyNum
                            val list = mutableListOf<String>()
                            for (i in response.body()!!.data.choiceWords.indices) {
                                list.add(response.body()!!.data.choiceWords[i].choiceWords)
                            }
                            val choiceChatData = OurUserChat(list, tag)
                            chatAdapter.addChat(choiceChatData)
                        }
                    }
                }
            })
    }
    private fun postReplyOneToServer(jwt: String, chatDetailsIdx: Int, replyNum: Int, replyString: String) {
        apophisService.getInstance()
            .requestOneReply(
                jwt = jwt,
                chatDetailsIdx = chatDetailsIdx,
                replyNum = replyNum,
                body = ReplyOneRequest(replyString)
            ).enqueue(object : Callback<BaseResponse<Unit>> {
                override fun onFailure(
                    call: Call<BaseResponse<Unit>>,
                    t: Throwable
                ) { //ํ†ต์‹  ์‹คํŒจ
                    Log.d("fail", t.message)
                }
                override fun onResponse(
                    call: Call<BaseResponse<Unit>>,
                    response: Response<BaseResponse<Unit>>
                ) {
                    if (response.isSuccessful) {
                        if (response.body()!!.success) {
                            if (chatDetailsIdx < 41) {
                                getAponymousChatFromServer(jwt, chatDetailsIdx + 1)
                                btn_chat_send.setImageResource(R.drawable.btn_send_unact)
                            }
                        }
                    }
                }
            })
    }
    private fun postReplyFourToServer(jwt: String, chatDetailsIdx: Int, replyNum: Int, reply: MutableList<String>) {
        apophisService.getInstance()
            .requestFourReply(
                jwt = jwt,
                chatDetailsIdx = chatDetailsIdx,
                replyNum = replyNum,
                body = ReplyFourRequest(reply[0], reply[1], reply[2], reply[3])
            ) .enqueue(object : Callback<BaseResponse<Unit>> {
                override fun onFailure(
                    call: Call<BaseResponse<Unit>>,
                    t: Throwable
                ) { //ํ†ต์‹  ์‹คํŒจ
                    Log.d("fail", t.message)
                }
                override fun onResponse(
                    call: Call<BaseResponse<Unit>>,
                    response: Response<BaseResponse<Unit>>
                ) {
                    if (response.isSuccessful) {
                        if (response.body()!!.success) {
                            if (chatDetailsIdx < 41) {
                                getAponymousChatFromServer(jwt, chatDetailsIdx + 1)
                                btn_chat_send.setImageResource(R.drawable.btn_send_unact)
                            }
                        }
                    }
                }
            })
    }
    private fun hideKeyboard() {
        val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(et_second_chat_message.windowToken, 0)
    }
    private fun snowBackground() {
        rcv_second_chat.setBackgroundResource(R.color.transparency00FF)
        cl_second_chat_bottom.setBackgroundResource(R.color.transparency00FF)
        cl_second_chat_header.setBackgroundResource(R.color.transparency00FF)
        constraintLayout_second.setBackgroundResource(R.drawable.bg_snowroadxx)
        Handler().postDelayed({
            rcv_second_chat.setBackgroundResource(R.color.black262627)
            cl_second_chat_bottom.setBackgroundResource(R.color.black2C2C2D)
            cl_second_chat_header.setBackgroundResource(R.color.black2C2C2D)
            constraintLayout_second.setBackgroundResource(R.color.black262627)
        }, 40000)
    }
}
class SecondDayChatAdapter(private val context: Context): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    private val userChatList: MutableList<OurUserChat> = mutableListOf()
    override fun getItemViewType(position: Int): Int {
        return when (userChatList[position].tag) {
            0 -> R.layout.item_chat_aponymous
            1 -> R.layout.item_chat_aponymous_image
            2 -> R.layout.item_aponymous_sound
            3, 9 -> R.layout.item_chat_user //9 ์žฅ๋ฌธํ˜•
            4 -> R.layout.item_chip_choice
            5 -> R.layout.item_chat_short_answer
            6 -> R.layout.item_chat_time
            7 -> R.layout.item_chat_find_me
            10 -> R.layout.item_chat_ending
            else -> R.layout.item_chat_value
        }
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            R.layout.item_chat_aponymous -> {
                val view = layoutInflater.inflate(R.layout.item_chat_aponymous, parent, false)
                AponymousViewHolder(view)
            }
            R.layout.item_chat_aponymous_image -> {
                val view = layoutInflater.inflate(R.layout.item_chat_aponymous_image, parent, false)
                AponymousImageViewHolder(view)
            }
            R.layout.item_aponymous_sound -> {
                val view = layoutInflater.inflate(R.layout.item_aponymous_sound, parent, false)
                AponymousSoundViewHolder(view)
            }
            R.layout.item_chat_user -> {
                val view = layoutInflater.inflate(R.layout.item_chat_user, parent, false)
                UserViewHolder(view)
            }
            R.layout.item_chip_choice -> {
                val view = layoutInflater.inflate(R.layout.item_chip_choice, parent, false)
                ChoiceChatViewHolder(view, layoutInflater)
            }
            R.layout.item_chat_short_answer -> {
                val view = layoutInflater.inflate(R.layout.item_chat_short_answer, parent, false)
                UserShortAnswerViewHolder(view, callbackListener)
            }
            R.layout.item_chat_time -> {
                val view = layoutInflater.inflate(R.layout.item_chat_time, parent, false)
                TimerActionViewHolder(view)
            }
            R.layout.item_chat_find_me -> {
                val view = layoutInflater.inflate(R.layout.item_chat_find_me, parent, false)
                FindMeActionViewHolder(view)
            }
            R.layout.item_chat_value -> {
                val view = layoutInflater.inflate(R.layout.item_chat_value, parent, false)
                ValueActionViewHolder(view)
            }
            R.layout.item_chat_ending -> {
                val view = layoutInflater.inflate(R.layout.item_chat_ending, parent, false)
                EndingViewHolder(view)
            }
            else ->
                throw IllegalArgumentException("ViewType [$viewType] is unexpected")
        }
    }
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is AponymousViewHolder) {
            holder.bind(userChatList[position].content)
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is AponymousImageViewHolder) {
            holder.bind(userChatList[position].content)
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is AponymousSoundViewHolder) {
            holder.bind(userChatList[position].content)
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is UserViewHolder) {
            holder.bind(userChatList[position].content)
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is ChoiceChatViewHolder) {
            holder.bind(userChatList[position].content)
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is UserShortAnswerViewHolder) {
            holder.bind(callbackListener)
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is TimerActionViewHolder) {
            holder.bind()
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is FindMeActionViewHolder) {
            holder.bind()
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is ValueActionViewHolder) {
            holder.bind()
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
        if (holder is EndingViewHolder) {
            holder.bind()
            holder.itemView.animation = AnimationUtils.loadAnimation(context, R.anim.translate_up)
        }
    }
    inner class AponymousViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val content = itemView.findViewById<TextView>(R.id.tv_aponymous_chat)
        fun bind(text: MutableList<String>) {
            text.forEach {
                content.text = it
            }
        }
    }
    inner class AponymousImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val image = itemView.findViewById<ImageView>(R.id.img_chat_aponymous)
        fun bind(imageUrl: MutableList<String>) {
            imageUrl.forEach {
                Glide.with(itemView).load(it).into(image)
            }
            image.background = context.getDrawable(R.drawable.round_rectangle_black_23dp)
            image.clipToOutline = true
        }
    }
    inner class AponymousSoundViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(text: MutableList<String>) {
        }
    }
    inner class UserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val content = itemView.findViewById<TextView>(R.id.tv_user_chat)
        fun bind(chatDataList: MutableList<String>) {
            chatDataList.forEach {
                content.text = it
            }
        }
    }
    inner class ChoiceChatViewHolder(itemView: View, inflater: LayoutInflater) : RecyclerView.ViewHolder(itemView) {
        private var chipGroup: ChipGroup = itemView.findViewById(R.id.chipgroup_choice)
        private val chipTextList: MutableList<String> = mutableListOf()
        private val inflater: LayoutInflater = inflater
        fun bind(chipItem: MutableList<String>) {
            chipGroup.removeAllViews()
            chipTextList.clear()
            chipItem.forEach {
                val chip = ChipFactory.newInstance(inflater)
                chip.text = it
                chip.isClickable = true
                chipGroup.addView(chip)
                chipTextList.add(it)
                chip.setOnClickListener {
                    itemClickListener.onItemClick(chip.text.toString())
                    // itemClickListener.onItemClick(chipTextList)
                }
            }
        }
    }
    inner class UserShortAnswerViewHolder(itemView: View, callbackListener: CallbackListener) : RecyclerView.ViewHolder(itemView) {
        private var num1: TextView = itemView.findViewById(R.id.tv_user_input_1)
        private var num2: TextView = itemView.findViewById(R.id.tv_user_input_2)
        private var num3: TextView = itemView.findViewById(R.id.tv_user_input_3)
        private var input: TextView = itemView.findViewById(R.id.tv_user_input)
        private var input1: TextView = itemView.findViewById(R.id.et_user_input_1)
        private var input2: TextView = itemView.findViewById(R.id.et_user_input_2)
        private var input3: TextView = itemView.findViewById(R.id.et_user_input_3)
        private var btnComplete: TextView = itemView.findViewById(R.id.btn_user_input_complete)
        private val inputTextList: MutableList<String> = mutableListOf()
        fun bind(callbackListener: CallbackListener) {
            input1.addTextChangedListener(object: TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                    num1.setTextColor(Color.parseColor("#AB70F5"))
                }
                override fun afterTextChanged(s: Editable?) {}
            })
            input2.addTextChangedListener(object: TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                    num2.setTextColor(Color.parseColor("#AB70F5"))
                }
                override fun afterTextChanged(s: Editable?) {}
            })
            input3.addTextChangedListener(object: TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                    num3.setTextColor(Color.parseColor("#AB70F5"))
                }
                override fun afterTextChanged(s: Editable?) {}
            })
            btnComplete.setOnClickListener {
                removeChat()
                inputTextList.add(input.text.toString())
                inputTextList.add("์ฒซ ๋ฒˆ์งธ๋Š” " + input1.text.toString())
                inputTextList.add("๋‘ ๋ฒˆ์งธ๋Š” " + input2.text.toString())
                inputTextList.add("์„ธ ๋ฒˆ์งธ๋Š” " + input3.text.toString())
                for (i in inputTextList.indices) {
                    val chatRight = OurUserChat(mutableListOf(inputTextList[i]), 3)
                    addChat(chatRight)
                }
                callbackListener.callBack(inputTextList)
            }
        }
    }
    inner class TimerActionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val btnAction = itemView.findViewById<ImageView>(R.id.btn_timer)
        fun bind() {
            btnAction.setOnClickListener {
                val intent = Intent(context, SecondDayTimepickerActivity::class.java)
                (context as Activity).startActivityForResult(intent, TIMER_ACTIVITY_REQUEST_CODE
                )
            }
        }
    }
    inner class FindMeActionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val btnAction = itemView.findViewById<ImageView>(R.id.btn_find_me)
        fun bind() {
            btnAction.setOnClickListener {
                itemClickListener.onItemClick("์ด๋Ÿฐ ๋ชจ์Šต๋“ค์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์•„.")
                val intent = Intent(context, SecondDayFindLightMeActivity::class.java)
                context.startActivity(intent)
            }
        }
    }
    inner class ValueActionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val btnAction = itemView.findViewById<ImageView>(R.id.btn_value)
        fun bind() {
            btnAction.setOnClickListener {
                itemClickListener.onItemClick("ํ–ˆ์–ด.")
                val intent = Intent(context, SecondDayValueActivity::class.java)
                context.startActivity(intent)
            }
        }
    }
    inner class EndingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val btnAction = itemView.findViewById<View>(R.id.btn_ending_okay)
        fun bind() {
            btnAction.setOnClickListener {
                val intent = Intent(context, SecondDayChatEndingActivity::class.java)
                context.startActivity(intent)
            }
        }
    }
    override fun getItemCount(): Int {
        return userChatList.size
    }
    fun addChat(userChatItem: OurUserChat) {
        userChatList.add(userChatItem)
        notifyItemInserted(userChatList.size)
    }
    fun removeChat() {
        userChatList.removeAt(userChatList.size-1)
        notifyItemRemoved(userChatList.size)
    }
    /* chip click listener */
    interface OnItemClickListener {
        fun onItemClick(data: String)
        // fun onItemClick(dataList: MutableList<String>)
    }
    private lateinit var itemClickListener: OnItemClickListener
    fun setOnItemClickListener(listener: OnItemClickListener) {
        this.itemClickListener = listener
    }
    /* callback listener */
    interface CallbackListener {
        fun callBack(inputTextList: MutableList<String>)
    }
    private lateinit var callbackListener: CallbackListener
    fun setCallbackListener(callbackListener: CallbackListener) {
        this.callbackListener = callbackListener
    }
    companion object {
        const val TIMER_ACTIVITY_REQUEST_CODE = 26
        // 26 = 2์ผ์ฐจ viewType 6
        const val FIND_ME_ACTIVITY_REQUEST_CODE = 27
        const val VALUE_ACTIVITY_REQUEST_CODE = 28
    }
}

drawble : ์•ฑ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ธ ์ฑ„ํŒ… ๊ตฌํ˜„ ๋กœ์ง ์ƒ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”, ๋น„ํ™œ์„ฑํ™” ๊ธฐ์ค€์ด ๋ทฐํƒ€์ž…๋งˆ๋‹ค ๋‹ฌ๋ผ์ง€๋Š” ๊ด€๊ณ„๋กœ ๊ฐœ๋ณ„ drawable์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.


๐ŸŽต Android developer & roles


๐Ÿ‘ฉ ๊น€๋‹คํ˜œ ๐Ÿ‘จ ํ•œ์žฌํ˜„ ๐Ÿ‘ฉ ์กฐ์„ฑ๋ฆผ
ํ”„๋กœํ•„ ํ”„๋กœํ•„ ํ”„๋กœํ•„
์Šคํ”Œ๋ž˜์‰ฌ
์Œ์•… ์žฌ์ƒ
๋ฉ”์ธ
ํŽธ์ง€ ๋ฐ›๊ธฐ/์“ฐ๊ธฐ
์˜จ๋ณด๋”ฉ ์•„ํฌํ”ผ์Šค ๋ทฐ
ํƒ€์ด๋จธ
์Œ์„ฑ ์†ก์ถœ
์ฑ„ํŒ… ์ „์ฒด ๋กœ์ง ๊ตฌํ˜„
์ฑ„ํŒ… ์—”๋”ฉ ๋ทฐ
2์ผ์ฐจ - ์ฑ„ํŒ… ๊ตฌํ˜„
2์ผ์ฐจ - ์‹œ๊ฐ„ ์„ค์ •
2์ผ์ฐจ - Find me
1์ผ์ฐจ - ์ฑ„ํŒ… ๊ตฌํ˜„
1์ผ์ฐจ - ๋‚˜์นจ๋ฐ˜
1์ผ์ฐจ - ์นด๋ฉ”๋ผ ์ดฌ์˜
1์ผ์ฐจ / 2์ผ์ฐจ - ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ด๋ฏธ์ง€ ์ „ํ™˜
2์ผ์ฐจ - ๊ฐ€์น˜๊ด€
7์ผ์ฐจ - ์ฑ„ํŒ… ๊ตฌํ˜„
7์ผ์ฐจ - ์œ ์„œ ์“ฐ๊ธฐ

About

Never-Die-Zombieroid โ˜„๐Ÿง›โ€โ™€๏ธ

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages