토이프로젝트로 영화 박스오피스 앱을 만들면서 꽤나 시간이 걸렸던 부분에 대해 기록한다.
본 영상처럼 Vertical Grid RecyclerView 안에 Horizon Linear RecyclerView를 넣도록 구현하고자 했다.
class HomeAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var data: List<HomeData> = emptyList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
RecyclerView.ViewHolder {
return when (viewType) {
TYPE_HEADER -> HeaderViewHolder(ItemHeaderBinding.inflate
(LayoutInflater.from(parent.context),parent,false))
TYPE_LIKE -> LikeViewHolder(ItemRecyclerLikeBinding.inflate
(LayoutInflater.from(parent.context),parent,false))
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when {
(holder is HeaderViewHolder && data[position].value is String)
-> holder.bind(data[position].value as String)
(holder is LikeViewHolder)
-> holder.bind(data[position].values!!)
else -> Unit
}
}
override fun getItemCount(): Int = data.size
override fun getItemViewType(position: Int): Int {
return when (data[position].value) {
is String -> TYPE_HEADER
else -> TYPE_LIKE
}
}
inner class HeaderViewHolder(private val binding: ItemHeaderBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(header: String) {
binding.title.text = header
}
}
inner class FeaturedViewHolder(private val binding: ItemFeaturedBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(featuredMovie: FeaturedMovie) {
Glide.with(binding.root)
.load(featuredMovie.posterUrl)
.into(binding.featuredMovieImageView)
binding.titleTextView.text = featuredMovie.title
binding.detailTextView.text =
"${featuredMovie.country} ' ${featuredMovie.releaseYear}"
}
}
inner class NormalViewHolder(private val binding: ItemMoviesBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(movie: Movie) {
binding.root.setOnClickListener {
onClickMovie?.invoke(movie)
}
Glide.with(binding.root)
.load(movie.posterUrl)
.into(binding.posterImageView)
binding.titleTextView.text = movie.title
binding.detailTextView.text = "${movie.country} ' ${movie.releaseYear}"
}
}
inner class LikeViewHolder(private val binding: ItemRecyclerLikeBinding) :
RecyclerView.ViewHolder(binding.root) {
init {
binding.recyclerView.apply {
adapter = LikeAdapter()
layoutManager =
LinearLayoutManager
(binding.root.context, RecyclerView.HORIZONTAL, false)
}
}
fun bind(likeMovies: List<LikeMovieEntity>) {
binding.emptyLikeTextView.isGone = true
binding.recyclerView.isVisible = true
(binding.recyclerView.adapter as LikeAdapter).apply {
addLikeMovie(likeMovies)
notifyDataSetChanged()
onClickLikeMovie = onClickLike
}
}
}
data class HomeData(val value: Any?, val values: List<LikeMovieEntity>?)
Main Adapter (바깥쪽 Vertical Grid RecyclerView Adapter) 에 대한 소스코드이다.
데이터를 새로운 HomeData라는 dataclass의 List 형태로 받아 이의 Type을 통해 view type을 설정한다.
찜 목록에 해당하는 데이터일 경우 view holder의 bind method에서 Like Adapter(안쪽 Horizon Linear Recyclerview Adapter)를 연결시켜주고, Like Adapter에 like movie entity list를 넘겨준다.
GitHub : https://github.com/HunSeongPark/box-office-MVVM