[Android/Kotlin] 안드로이드 Section(Group) RecyclerView 만들기
안녕하세요. 오늘은 Section 또는 Group RecyclerView에 대해서 알아보겠습니다.
여기서 말하는 Section 또는 Group이라는 말은 대분류안에 소분류가 있다고 생각하시면 될 것 같습니다.
예를들어 데이터를 일단 날짜별로 일단 보여주고, 해당날짜에 상세 내역을 보여주는 용도로 보면 될 것 같습니다.
그래서 오늘은 아래와 같은 시나리오를 준비했습니다.
1. 그룹(고등학교, 대학교, 직장 등) 리스트 보여주기
2. 그룹 내 친구 리스트 보여주기
완성된 모습은 아래와 같습니다.
STEOP01. 데이터 클래스 만들기
두가지 데이터 클래스가 존재합니다.
하나는 그룹별 친구리스트를 보여주는 SectionModel 클래스이고, 친구 정보를 담는 Friend 클래스를 만들어 줍니다.
[SectionModel.kt]
data class SectionModel(
val category: String,
val friendList: List<Friend>
)
[Friend.kt]
data class Friend(
val name: String,
val age: Int,
val phone: String
)
STEOP02. Fake Data 만들기
MainActivity 파일에서 아래와 같이 데이터 값을 생성해 줍니다.
[MainActivity.kt]
private val friendModelList = ArrayList<SectionModel>()
private fun loadFakeData() {
val firstCategory = "고등학교"
val firstFriends = ArrayList<Friend>()
firstFriends.add(Friend("이순신", 32, "010-1234-1111"))
firstFriends.add(Friend("홍길동", 13, "010-1234-1112"))
firstFriends.add(Friend("강감찬", 13, "010-1234-1113"))
firstFriends.add(Friend("연개소문", 13, "010-1234-1114"))
val secondCategory = "대학교"
val secondFriends = ArrayList<Friend>()
secondFriends.add(Friend("머스크", 24, "010-1234-1115"))
secondFriends.add(Friend("빌게이츠", 44, "010-1234-1116"))
secondFriends.add(Friend("워렌버핏", 55, "010-1234-1117"))
val thirdCategory = "직장"
val thirdFriends = ArrayList<Friend>()
thirdFriends.add(Friend("이재용", 45, "010-1234-1118"))
thirdFriends.add(Friend("손흥민", 32, "010-1234-1119"))
thirdFriends.add(Friend("김연아", 55, "010-1234-1120"))
thirdFriends.add(Friend("손연재", 37, "010-1234-1121"))
thirdFriends.add(Friend("정우성", 42, "010-1234-1122"))
thirdFriends.add(Friend("손아섭", 41, "010-1234-1123"))
friendModelList.add(SectionModel(firstCategory, firstFriends))
friendModelList.add(SectionModel(secondCategory, secondFriends))
friendModelList.add(SectionModel(thirdCategory, thirdFriends))
}
FriendAdapter 클래스를 생성할 때 위에서 만든 데이터를 넘겨줍니다.
private fun setupRecyclerView() {
binding.rvFriend.apply {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = FriendAdapter(friendModelList)
}
}
STEOP03. Adapter 클래스 만들기
일반적인 Adapter 클래스입니다.
레이아웃에 RecyclerView가 존재하기때문에 bind할때 FriendSubAdapter 클래스도 생성해줍니다.
FriendAdpater에서는 그룹을 만들어주고, FriendSubAdapter에서는 그룹 내 친구 목록을 만들어줍니다.
[FriendAdapter.kt]
class FriendAdapter(
private val friendModelList: List<SectionModel>
) : RecyclerView.Adapter<FriendAdapter.MyViewHolder>() {
class MyViewHolder(
private val binding: ItemSectionBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(sectionModel: SectionModel) {
binding.txtCategory.text = sectionModel.category
binding.txtTotal.text = "${sectionModel.friendList.size}명"
binding.rvSubFriend.apply {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(binding.root.context)
adapter = FriendSubAdapter(sectionModel.friendList)
addItemDecoration(
DividerItemDecoration(binding.root.context,
DividerItemDecoration.VERTICAL)
)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(ItemSectionBinding.inflate(LayoutInflater.from(parent.context),
parent, false))
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(friendModelList[position])
}
override fun getItemCount() = friendModelList.size
}
[FriendSubAdapter.kt]
class FriendSubAdapter(
private val friendList: List<Friend>
) : RecyclerView.Adapter<FriendSubAdapter.MyViewHolder>() {
class MyViewHolder(
private val binding: ItemSubSectionBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(friend: Friend) {
with(binding) {
txtName.text = friend.name
txtAge.text = "${friend.age}"
txtPhone.text = friend.phone
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(ItemSubSectionBinding.inflate(LayoutInflater.from(parent.context),
parent, false))
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(friendList[position])
}
override fun getItemCount() = friendList.size
}
ViewHolder와 관련한 레이아웃은 아래와 같습니다.
[item_section.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<TextView
android:id="@+id/txt_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black"
android:background="@android:color/darker_gray"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="학교"/>
<TextView
android:id="@+id/txt_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@color/black"
android:background="@android:color/darker_gray"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="3명"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_sub_friend"
android:overScrollMode="never"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/txt_category"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
[item_sub_section.xml]
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/txt_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:layout_marginStart="16dp"
android:textStyle="bold"
android:textColor="@color/black"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="홍길동"/>
<TextView
android:id="@+id/txt_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:text="32"/>
<TextView
android:id="@+id/txt_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/txt_name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:text="010-1234-1111"/>
</androidx.constraintlayout.widget.ConstraintLayout>
코드가 완성되었습니다. 메인 액티비티 전체코드는 아래와 같습니다.
[MainActivity.kt]
class MainActivity : AppCompatActivity() {
private var _binding: ActivityMainBinding? = null
private val binding get() = _binding!!
private val friendModelList = ArrayList<SectionModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
loadFakeData()
setupRecyclerView()
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
private fun setupRecyclerView() {
binding.rvFriend.apply {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = FriendAdapter(friendModelList)
}
}
private fun loadFakeData() {
val firstCategory = "고등학교"
val firstFriends = ArrayList<Friend>()
firstFriends.add(Friend("이순신", 32, "010-1234-1111"))
firstFriends.add(Friend("홍길동", 13, "010-1234-1112"))
firstFriends.add(Friend("강감찬", 13, "010-1234-1113"))
firstFriends.add(Friend("연개소문", 13, "010-1234-1114"))
val secondCategory = "대학교"
val secondFriends = ArrayList<Friend>()
secondFriends.add(Friend("머스크", 24, "010-1234-1115"))
secondFriends.add(Friend("빌게이츠", 44, "010-1234-1116"))
secondFriends.add(Friend("워렌버핏", 55, "010-1234-1117"))
val thirdCategory = "직장"
val thirdFriends = ArrayList<Friend>()
thirdFriends.add(Friend("이재용", 45, "010-1234-1118"))
thirdFriends.add(Friend("손흥민", 32, "010-1234-1119"))
thirdFriends.add(Friend("김연아", 55, "010-1234-1120"))
thirdFriends.add(Friend("손연재", 37, "010-1234-1121"))
thirdFriends.add(Friend("정우성", 42, "010-1234-1122"))
thirdFriends.add(Friend("손아섭", 41, "010-1234-1123"))
friendModelList.add(SectionModel(firstCategory, firstFriends))
friendModelList.add(SectionModel(secondCategory, secondFriends))
friendModelList.add(SectionModel(thirdCategory, thirdFriends))
}
}
'기리's Android 이야기' 카테고리의 다른 글
[Android/Kotlin] 안드로이드 Room Database 사용하기(2) Select... (1) | 2021.02.01 |
---|---|
[Android/Error] 안드로이드 ViewModelProvider 에러발생 (0) | 2021.01.31 |
[Android/Kotlin] 안드로이드 Room Database 사용하기(1) (1) | 2021.01.30 |
[Android/Kotlin] 안드로이드 Spinner 커스텀 해보기(3) feat. Drop Down Menu (2) | 2021.01.30 |
[Android/Kotlin] 안드로이드 Spinner 커스텀 해보기(2) feat. Hint 만들기 (0) | 2021.01.30 |
댓글