Android/Study

[Android] A RecyclerView with multiple item types in Kotlin에 대해서 공부하자

Tenacity_Dev 2024. 6. 9. 15:25
728x90

RecyclerView with multiple item types in Kotlin이란?

개발을 하다보면 여러 개의 Recycler View를 만들게 되어 프로젝트 구조가 복잡해지기 마련이다. 예를 들면 하나의 Recycler View에 여러 타입의 뷰를 띄워야 하는 경우도 있습니다. 예를 들면, 네이버 카페 어플에서 글을 본다고 할 때, 사진+제목, 제목, 광고와 같은 타입으로 아이템이 나눠질 수 있다.

 

하나의 View에는 하나의 DataItem밖에 들어가야하지 않을까?

나도 처음에는 그렇게 생각하였지만 공부를 하면서 그렇게 하지 않아도 된다는 점을 발견하였다.

 

여러가지 방법이 있다.

 

하지만 이번 포스팅에서는 "Sealed Class를 활용해서 ViewHolder와 Item 묶어내는 방법"으로 Mutiple item types를 구현했다.

아래는 프로젝트 코드이다.

 

MovieData

val movies : MutableList<MovieItems> = mutableListOf<MovieItems>().apply {
    add(MovieItems.TextMovie(1, "이미지 없는 영화1"))
    add(MovieItems.ImageMovie(2, R.drawable.post1, "스마일"))
    add(MovieItems.TextMovie(3, "이미지 없는 영화2"))
    add(MovieItems.ImageMovie(4, R.drawable.post2, "노량"))
    add(MovieItems.TextMovie(5, "이미지 없는 영화3"))
    add(MovieItems.ImageMovie(6, R.drawable.post3, "범죄도시3"))
    add(MovieItems.TextMovie(7, "이미지 없는 영화4"))
    add(MovieItems.ImageMovie(8, R.drawable.post4, "서울의 봄"))
    add(MovieItems.TextMovie(9, "이미지 없는 영화5"))
    add(MovieItems.ImageMovie(10, R.drawable.post5, "실미도"))
    add(MovieItems.TextMovie(11, "이미지 없는 영화6"))
    add(MovieItems.ImageMovie(12, R.drawable.post6, "파묘"))
    add(MovieItems.TextMovie(13, "이미지 없는 영화7"))
}

 

sealed Class MovieItems

sealed class MovieItems {
    data class ImageMovie(
        val id: Int, val image: Int, val title: String
    ) : MovieItems()

    data class TextMovie(
        val id: Int, val title: String
    ) : MovieItems()
}

 

 

ImageViewHolder

class ImageViewHolder(
    private val binding: ItemImageMovieBinding
) : RecyclerView.ViewHolder(binding.root)  {
    fun bind(item: MovieItems.ImageMovie) = with(binding){
        previewImageView.setImageResource(item.image)
        movieTitle.text = item.title
    }
}

 

TitleViewHolder

class TitleViewHolder(
    private val binding: ItemTitleMovieBinding
) : RecyclerView.ViewHolder(binding.root) {
    fun bind(item: MovieItems.TextMovie) = with(binding){
        MovieTitleView.text = item.title
    }
}

 

 

MovieAdapter

class MovieAdapter : ListAdapter<MovieItems, RecyclerView.ViewHolder>(diffCallback) {

    override fun getItemViewType(position: Int): Int {
        return when (currentList[position]) {
            is MovieItems.ImageMovie -> ITEM_IMAGE
            is MovieItems.TextMovie -> ITEM_TITLE
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        Log.d("RecyclerView", "onCreateViewHolder")
        val layoutInflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            ITEM_IMAGE -> {
                val binding = ItemImageMovieBinding.inflate(layoutInflater, parent, false)
                ImageViewHolder(binding)
            }

            else -> {
                val binding = ItemTitleMovieBinding.inflate(layoutInflater, parent, false)
                TitleViewHolder(binding)
            }
        }
    }


    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        Log.d("RecyclerView", "onBindViewHolder $position")
        when (holder) {
            is ImageViewHolder -> {
                holder.bind(currentList[position] as MovieItems.ImageMovie)
            }

            is TitleViewHolder -> {
                holder.bind(currentList[position] as MovieItems.TextMovie)
            }
        }
    }

    companion object {
        private val diffCallback = object : DiffUtil.ItemCallback<MovieItems>() {
            override fun areItemsTheSame(oldItem: MovieItems, newItem: MovieItems): Boolean {
                return oldItem === newItem
            }

            override fun areContentsTheSame(oldItem: MovieItems, newItem: MovieItems): Boolean {
                return oldItem == newItem
            }
        }

        const val ITEM_IMAGE = 0
        const val ITEM_TITLE = 1
    }
}

 

실행화면

 

 

 

프로젝트 링크

https://github.com/ois0886/Android_Side_Projects/tree/main/RecyclerViewStudy

 

Android_Side_Projects/RecyclerViewStudy at main · ois0886/Android_Side_Projects

혼자 공부하면서 만들어본 간단한 프로젝트 모음입니다. Contribute to ois0886/Android_Side_Projects development by creating an account on GitHub.

github.com

 

참고

https://rccode.tistory.com/285

 

[Kotlin] Multiple View Types를 지원하는 RecyclerView 구현

서론 결과 미리보기 배경 개발을 하다보면 여러 개의 Recycler View를 만들게 되어 프로젝트 구조가 복잡해지기 마련입니다. 또한 위 사진처럼 하나의 Recycler View에 여러 타입의 뷰를 띄워야 하는 경

rccode.tistory.com

https://developer-munny.tistory.com/2

 

[Android/Kotlin] Multi-ViewType을 사용하는 RecyclerView의 구조를 추상화 해보기

수정일: 2021/5/12 - class 이름 변경 RecyclerView를 사용하다보면 하나의 아이템만 보여주는것이 아니라 다양한 형태의 아이템을 보여주고 싶을 때가 있습니다. 여러 타입의 아이템을 보여주는 데에는

developer-munny.tistory.com

https://medium.com/@ruut_j/a-recyclerview-with-multiple-item-types-in-kotlin-80e1e36d93e6

 

A RecyclerView with multiple item types in Kotlin

It's been already 7 years ago that I wrote this article about multiple RecyclerView item types.

medium.com

 

728x90