본문 바로가기

[Android/Kotlin] 안드로이드 Section(Group) RecyclerView 만들기

꿈꾸는블로그왕 2021. 1. 31.

안녕하세요. 오늘은 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))
    }
    
}

 

 

 

 

댓글