일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- android recyclerview
- Android 12
- 안드로이드 갤러리 접근
- Android WebView
- Kotlin FCM
- Android Interceptor
- scope function
- Android DataBinding
- DataBinding
- 안드로이드
- Android ProgressBar
- OkHttp Interceptor
- 영어독립365
- 알고리즘 자바
- Android 12 대응
- Android
- 카카오 알고리즘
- Android ViewPager2
- 습관만들기
- 영어공부
- 안드로이드 카카오 로그인
- Java
- Android Navigation
- 66챌린지
- 프로그래머스 알고리즘
- Kotlin
- Android Jetpack
- MVP Architecture
- WebView
- 안드로이드 fcm
Archives
- Today
- Total
Developer Geek
[Android] RecyclerView Multi-ViewHolder Basic Sample: 채팅 화면 본문
반응형
개요
앱 설명
RecyclerView에서 Multi-ViewHolder를 이용하여 메신저 어플리케이션에서 보여지는 UI를 만든다.
실행화면
Code
프로젝트 구조
build.gradle(:Module): ViewBinding 셋팅
android {
...
buildFeatures{
viewBinding true
}
}
MessageModel.kt
interface MessageModel {
data class SenderMessage(
val message: String
): MessageModel
data class ReceiverMessage(
val message: String
): MessageModel
}
RecyclerView의 Multi-ViewHolder에서 사용할 아이템 아이템을 일반화 하기 위해서 Interface로 MessageModel
를 만든다.
그리고 사용할 아이템 타입을 정의하는 클래스를 정의하는데 MessageModel
을 상속받는다.
item_sender_chat.xml
SenderViewHolder
에서 사용할 Layout을 구현한다.
<androidx.constraintlayout.widget.ConstraintLayout 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_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="100dp"
android:backgroundTint="#FFC107"
app:cardCornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:padding="10dp"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
tools:text="나의 메시지 나의 메시지" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
SenderViewHolder.kt
class SenderViewHolder(private val binding: ItemSenderChatBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bindItem(senderMessage: MessageModel.SenderMessage) {
binding.tvMessage.text = senderMessage.message
}
companion object {
fun create(parent: ViewGroup): SenderViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = ItemSenderChatBinding.inflate(layoutInflater, parent, false)
return SenderViewHolder(view)
}
}
}
item_receiver_chat.xml
ReceiverViewHolder
에서 사용할 Layout을 구현한다.
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:layout_margin="10dp">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:backgroundTint="#4CAF50"
app:cardCornerRadius="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:padding="10dp"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
tools:text="상대방 메시지 상대방 메시지" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
ReceiverViewHolder.kt
class ReceiverViewHolder(private val binding: ItemReceiverChatBinding): RecyclerView.ViewHolder(binding.root) {
fun bindItem(receiverMessage: MessageModel.ReceiverMessage){
binding.tvMessage.text = receiverMessage.message
}
companion object {
fun create(parent: ViewGroup): ReceiverViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = ItemReceiverChatBinding.inflate(layoutInflater, parent, false)
return ReceiverViewHolder(view)
}
}
}
ChatAdapter.kt
class ChatAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val itemList = arrayListOf<MessageModel>()
fun addItem(item: MessageModel){
itemList.add(item)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when(viewType){
TYPE_SENDER -> SenderViewHolder.create(parent)
else -> ReceiverViewHolder.create(parent)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when(holder){
is SenderViewHolder -> holder.bindItem(itemList[position] as SenderMessage)
is ReceiverViewHolder -> holder.bindItem(itemList[position] as ReceiverMessage)
}
}
override fun getItemCount(): Int {
return itemList.size
}
override fun getItemViewType(position: Int): Int {
return when(itemList[position]){
is SenderMessage -> TYPE_SENDER
is SenderMessage -> TYPE_RECEIVER
else -> -1
}
}
companion object{
const val TYPE_SENDER = 0
const val TYPE_RECEIVER = 1
}
}
itemList = arrayListOf<MessageModel>()
: ViewHolder에 사용될 아이템을 일반화(MessageModel
)한 리스트.(MessageModel
을 상속받아 구현한SenderMessage
또는ReceiverMessage
모두 아이템이 될 수 있다.)getItemViewType(position: Int)
:itemList[position]
의 타입이 SenderMessage인 경우,TYPE_SENDER
를 반환하고 ReceiverMessage인 경우,TYPE_RECEIVER
를 반환한다. 반환된 viewYpe을 통해서onCreateViewHolder(parent: ViewGroup, viewType: Int)
에서 ViewHolder를 생성할 때 사용한다.onCreateViewHolder(parent: ViewGroup, viewType: Int)
: viewType에 따른SenderViewHolder
또는ReceiverViewHolder
를 생성하여 반환한다.
activity_main.xml
androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvChatting"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#7A03A9F4"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val chatAdapter = ChatAdapter()
chatAdapter.apply {
addItem(SenderMessage("안녕하세요."))
addItem(SenderMessage("저는 안드로이드 개발자입니다."))
addItem(ReceiverMessage("반갑습니다!!"))
addItem(SenderMessage("당신은 어떤 개발자입니까?"))
addItem(ReceiverMessage("저는 안드로이드 신입 개발자에요. :)"))
addItem(SenderMessage("반가워요."))
}
binding.rvChatting.adapter = chatAdapter
}
}
질문과 잘못된 점에 대해 말씀해주시는 건 언제나 환영입니다.
zero5.two4@gmail.com
반응형
'안드로이드 > View' 카테고리의 다른 글
[Android] Spannable Click Event Example (0) | 2022.09.25 |
---|---|
[Android] RecyclerView 아이템 여백 설정 (1) | 2022.09.24 |
[Android] ViewPager2 Basic Sample in Kotlin (0) | 2022.08.10 |
[Android] ViewPager Basic Sample in Kotlin (0) | 2022.08.08 |
[Android] ViewPager2 and TabLayout Sample in Kotlin (0) | 2022.07.28 |
Comments