본문 바로가기
Android & Kotlin/Android

[안드로이드 코틀린] 리사이클러뷰 뷰타입에 따른 설정 (실습 : 채팅방)

by 말린밴댕이_공부 2023. 5. 13.
반응형

채팅방에 대한 리사이클러뷰를 통해 진행을 하려할때 뷰타입에 따른 설정을 진행하는 것에 대한 예제에 대한 학습을 적으려 합니다.

 

알고보면 간단하지만 알기전에는 힘든 친구가 아닐까 생각하네요.

 

val chatAdapter = ChattingChatAdapter(chatList)
binding.rvChattingChat.apply {
    adapter = chatAdapter
    layoutManager = LinearLayoutManager(context,LinearLayoutManager.VERTICAL,true)

}
viewModel.messageList.observe(viewLifecycleOwner, Observer { messages->
    messages.forEach {chatAdapter.addMessage(it)}
    binding.rvChattingChat.scrollToPosition(0)
})

//테스트 데이터 추가
chatList.forEach { viewModel.addMessage(it) }

  

우선 액티비티나 프래그먼트에서 이렇게 viewmodel을 이용해 이용하였습니다.

observe를 통해 향후에 이제 메세지를 주고 받을때 리사이클러뷰에 대한 메세지를 추가를 진행해주기 위해 진행하였습니다.

 

아직 서버와 통신을 진행하고 있지 않지만 나중을 위해 이런식으로 설정을 해두었습니다 :)

 

이제 adapter에 대한 코드를 하나씩 뜯어 보겠습니다.

class ChattingChatAdapter(var chattingMessageResult: List<ChattingMessageResult>)
    : RecyclerView.Adapter<ChattingChatAdapter.MessageViewHolder>() {

    private val messages = mutableListOf<ChattingMessageResult>()

    companion object {
        private const val VIEW_TYPE_MINE = 0
        private const val VIEW_TYPE_OTHER = 1
    }

    fun addMessage(message : ChattingMessageResult){
        messages.add(0,message)
        notifyItemInserted(0)
    }

    override fun getItemViewType(position: Int): Int = when (messages[position].userId) {
        0 -> VIEW_TYPE_MINE
        else -> VIEW_TYPE_OTHER
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = when (viewType){
            VIEW_TYPE_MINE -> ChattingMineListBinding.inflate(inflater,parent,false)
            else -> ChattingOtherListBinding.inflate(inflater,parent,false)
        }
        return MessageViewHolder(binding)
    }
    override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
        holder.bind(messages[position])
    }

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

    inner class MessageViewHolder(private val binding : ViewBinding) : RecyclerView.ViewHolder(binding.root){
        fun bind(chattingMessageResult: ChattingMessageResult){
            when(binding){
                is ChattingMineListBinding ->{
                    binding.tvChattingMine.text = chattingMessageResult.message
                    binding.tvChattingMineWhen.text = chattingMessageResult.time
                }
                is ChattingOtherListBinding -> {
                    binding.tvChattingOtherMessage.text = chattingMessageResult.message
                    binding.tvChattingOtherWhen.text = chattingMessageResult.time
                    if(chattingMessageResult.isFirst){
                        Glide.with(itemView).load(chattingMessageResult.userProfile)
                            .circleCrop().into(binding.ivChattingOtherProfile)
                    }else{
                        binding.ivChattingOtherProfile.visibility = View.GONE
                    }
                }
            }
        }
    }

}

 

 

override fun getItemViewType(position: Int): Int = when (messages[position].userId) {
    0 -> VIEW_TYPE_MINE
    else -> VIEW_TYPE_OTHER
}

뷰타입을 통해 임시적으로 userId 가 0일때는 자신 아닐때는 상대방이 되겠습니다.

-> 임시적이라 향후 서버와의 연결이 된다면 자신의 userId를 아마 sharedpreferences에 넣어두고 사용하지 않을까 싶습니다.

 

fun addMessage(message : ChattingMessageResult){
    messages.add(0,message)
    notifyItemInserted(0)
}

이제 메세지를 입력하거나 메세지를 수령했을때 메세지를 추가하고 삽입에 대한 것을 리사이클러뷰에 갱신을 해주어야 하기 때문에 이렇게 진행하였습니다.

 

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
    val inflater = LayoutInflater.from(parent.context)
    val binding = when (viewType){
        VIEW_TYPE_MINE -> ChattingMineListBinding.inflate(inflater,parent,false)
        else -> ChattingOtherListBinding.inflate(inflater,parent,false)
    }
    return MessageViewHolder(binding)
}

이제 createviewholder에 binding을 정할때 viewtype이 나 혹은 상대방들에 대해서 설정을 진행해주고 MessageViewhler(binding)을 return 해주었습니다.

 

아래의 onBindViewholder와 getItemCount와 viewholder에 대해서는 기본적인 형태와 똑같기 때문에 설명을 진행하지 않도록 하겠습니다.

 

이제 이렇게 진행을 해준다면 채팅방과 같은 리사이클러뷰를 완성하실 수 있습니다.

반응형

댓글