View
RecyclerView 내부 아이템에 RecyelerView가 필요할 때?
개인 프로젝트인 로스트아크 앱을 개발하는 도중 RecyclerView안에 있는 Item 값안에 RecyclerView가 필요한 경우가 생기게 되었다.
위 사진 처럼 모험 섬이라는 Item안에 각각의 보상 아이템 이미지가 들어가는 경우다.
즉 모험 섬이 부모 RecyclerView의 Item이고 각각의 보상 아이템 이미지가 자식 RecyclerView의 Item이 된다.
어떻게 해야될까?
해당 문제가 생겼을 때 처음에 난 매우 간단히 생각했다.
바로 해당 부모 RecyclerView Item안에 RecyclerView를 선언 해서 만든는 법이다.
여기까지는 무척 좋았다. 간단하지만 생각 못했던 문제를 만나기 전까지는....
일단 나는 각각의 Item layout를 작성해주었다.
[item_andventure_island.xml] 모험 섬 Item
아래 코드를 보면 RecyclerView가 들어간 것을 볼 수 있다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_outbalck_inwhite_thin_round_bg">
<TextView
android:id="@+id/tv_island_name_item"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:gravity="center"
android:text="섬 이름"
android:textColor="@color/white"
android:textSize="20dp"
android:background="@drawable/tv_background_gradient_center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_island_image_item"
android:layout_width="200dp"
android:layout_height="150dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_reward_tag"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:gravity="left"
android:text="기대 모험 보상"
android:textColor="@color/clr_D6D6D6"
android:textSize="15dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_island_image_item" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_reward_item"
android:layout_width="200dp"
android:layout_height="100dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_reward_tag"/>
</androidx.constraintlayout.widget.ConstraintLayout>
[item_reward_image.xml] 보상 아이템 이지미 Item
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_marginTop="5dp"
android:layout_marginStart="5dp">
<ImageView
android:id="@+id/iv_reward_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="30dp"
android:layout_height="30dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
[AdventureIslandAdapter] 모험 섬 adapter
class AdventureIslandAdapter(
// private val matchPlayerRecyclerListener: MatchPlayerRecyclerListener,
private val contentsCalendarResultList: ArrayList<ContentsCalendarResult>,
) : RecyclerView.Adapter<AdventureIslandViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AdventureIslandViewHolder {
val itemBinding =
ItemAdventureIslandBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return AdventureIslandViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: AdventureIslandViewHolder, position: Int) {
holder.bind(contentsCalendarResultList[position])
}
override fun getItemCount(): Int {
return contentsCalendarResultList.size
}
}
[AdventureIslandViewHolder] 모험 섬 ViewHolder
class AdventureIslandViewHolder(
private val binding: ItemAdventureIslandBinding,
) : RecyclerView.ViewHolder(binding.root) {
fun bind(contentsCalendarResult: ContentsCalendarResult) {
binding.tvIslandNameItem.text = contentsCalendarResult.contentsName
Glide.with(itemView.context)
.load(contentsCalendarResult.contentslcon)
.error(R.drawable.painter1)
.placeholder(R.drawable.painter2)
.fitCenter()
// .override(1200, 700)
.into(binding.ivIslandImageItem)
binding.rvRewardItem.apply {
//여기에 어떻게 보상 아이템 이미지의 adapter를 연결할지....
//context가 필요하다. Manager를 하기 위해서는.....
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL,false)
adapter = RewardItemAdapter(context,contentsCalendarResult.rewardItems)
}
}
}
문제 발생 및 해결
간단히 ViewHolder를 작성 중 문제가 발생하고 말았다.
보통 RecyclerView의 adapter를 연결할 때 LinearLayoutManager를 사용하는데 여기에 파라미터 값으로 해당 Activity의 context가 필요하다. 그렇지만 ViewHolder에는 따로 context가 있지 않기 때문에 어떻게 해야될까라는 고민을 할 수 있다.
나도 처음 안드로이드를 개발할 때는 잘이해하지 못해서 여기서 막혔다. 하지만 지금 생각해보면 의외로 간단한 방법이 있다.
바로 Activity에서 context를 인자로 받아서 그냥 adapter와 ViewHolder까지 끌고 오는 방법이다.
[AdventureIslandAdapter] 모험 섬 adapter 해결 후
class AdventureIslandAdapter(
private val context: Context,
// private val matchPlayerRecyclerListener: MatchPlayerRecyclerListener,
private val contentsCalendarResultList: ArrayList<ContentsCalendarResult>,
) : RecyclerView.Adapter<AdventureIslandViewHolder>(){
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AdventureIslandViewHolder {
val itemBinding =
ItemAdventureIslandBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return AdventureIslandViewHolder(itemBinding)
}
override fun onBindViewHolder(holder: AdventureIslandViewHolder, position: Int) {
holder.bind(context, contentsCalendarResultList[position])
}
override fun getItemCount(): Int {
return contentsCalendarResultList.size
}
}
[AdventureIslandViewHolder] 모험 섬 ViewHolder 해결 후
class AdventureIslandViewHolder(
private val binding: ItemAdventureIslandBinding,
) : RecyclerView.ViewHolder(binding.root) {
fun bind(context: Context, contentsCalendarResult: ContentsCalendarResult) {
binding.tvIslandNameItem.text = contentsCalendarResult.contentsName
Glide.with(itemView.context)
.load(contentsCalendarResult.contentslcon)
.error(R.drawable.painter1)
.placeholder(R.drawable.painter2)
.fitCenter()
// .override(1200, 700)
.into(binding.ivIslandImageItem)
binding.rvRewardItem.apply {
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL,false)
adapter = RewardItemAdapter(context,contentsCalendarResult.rewardItems)
}
}
}
바로 이렇게 context를 가져오면된다. 이렇게 하면 이중 RecyclerView의 문제를 해결할 수 있다. ㅎㅅㅎ
현재..Rxjava 늪에 빠졌다..아...에휴....3일째....
'TIL' 카테고리의 다른 글
앱 아이콘 설정하기 (0) | 2024.02.23 |
---|---|
Rxjava 적용(4일째 고민...) (1) | 2024.02.19 |
변수와 상수 (2) | 2024.02.14 |
자료형이란? (1) | 2024.02.13 |
Convention란? (0) | 2024.02.13 |