-
Multi View Type RecyclerViewAndroid 2024. 4. 29. 21:10

multi view type 예제 오늘은 recyclerView 중 viewtype이 한개가 아닌 여러개인 multi viewtype recyclerView 에 대해서 핵심 개념과 코드를 포스팅 하려고 한다. 위의 gif 를 보면 카드에 색깔이 3개이다. 색깔을 기준으로 viewtype을 나누려고 한다.
// Card.kt @Parcelize data class Card( .. val cardViewType: MultiViewEnum ):Parcelableviewtype 을 다르게 받아오기 위해서는 data class 에서 viewtype 을 지정할 수 있는 변수를 선언을 해야한다.
// MultiViewEnum.kt enum class MultiViewEnum(val viewType: Int) { BLUE(0), LIGHTBLUE(1), ORANGE(2) }viewtype 을 지정하기 위해 enum class를 생성한다. viewType은 기본값으로 0부터 시작하니, 원하는 갯수만큼 담아주면 된다.
1. 어댑터 내에서 getItemViewType 메소드 오버라이딩
// MultiCardAdapter.kt override fun getItemViewType(position: Int): Int { // position 과 itemviewtype 을 연결시킴 return when (position) { 0 -> MultiViewEnum.BLUE.viewType 1 -> MultiViewEnum.LIGHTBLUE.viewType 2 -> MultiViewEnum.ORANGE.viewType else -> throw IllegalArgumentException("Invalid position") } }viewType 이 한개로 지정되어있으면 해당 메소드를 오버라이딩 할 필요 없지만, viewType 이 여러개인 경우 해당 함수를 오버라이딩 하는 것은 꼭 필요하다. 이때, position 은 리스트에 담겨있는 데이터 객체의 갯수를 의미하며, 0부터 시작한다.
해당 코드는 아까 MultiViewEnum 코드랑 연관성이 있다. position마다 viewType을 다르게 명시해서 매치시키면 된다.
이러면, BLUE, LIGHTBLUE, ORANGE 이런 식으로 명시해서 각 색깔의 viewtype을 찾기가 더 쉽다.
2. type 별로 viewholder 정의
// MultiCardAdapter.kt class MultiCardAdapter(private val onClick: (Card) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { var cardList = listOf<Card>() inner class BlueTypeViewHolder(private val binding: ItemBlueCardBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(card: Card) { // onBindViewHolder에서 해당 함수를 불러와서 씀, 정의 자체는 ViewHolder에서 함 binding.apply { tvUsername.text = card.userName tvCardNum.text = card.cardNumber tvCardType.text = card.cardType tvCardPeriod.text = card.period tvBalance.text = card.balance.toString() tvCardManager.text = card.cardManager } } } ... }아까, enum class 에서 blue, lightblue, orange 3가지로 viewtype 을 나누어줬다.
똑같이 어댑터에서 viewholder도 총 3개 만들어주면 된다.
bind 함수를 만들고 내부 코드를 뷰홀더에서 정의한다. (해당 함수의 사용은 onBindViewHolder 에서 한다.)
3. 정의한 뷰홀더를 가지고 생성
// MultiCardAdapter.kt override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { MultiViewEnum.BLUE.viewType -> { // binding 만들고 ViewHolder에다가 binding 넣어서 ViewHolder 생성하기! val binding = ItemBlueCardBinding.inflate(LayoutInflater.from(parent.context), parent, false) BlueTypeViewHolder(binding) } MultiViewEnum.LIGHTBLUE.viewType -> { // 같은 구조여서 생략 } MultiViewEnum.ORANGE.viewType -> { // 같은 구조여서 생략 } else -> throw IllegalArgumentException("Invalid view type") } }viewtype을 아까 enum class 에서 BLUE의 경우에는 0, LIGHTBLUE의 경우에는 1, ORANGE의 경우에는 2로 받아줬다.
onCreateViewHolder에서는 인자로 viewtype이 같이 넘어오는데, 이때 when절로 분기를 해서 viewtype별로 다른 로직을 처리해주면 된다.
return when 절에서는 마지막에 else를 꼭 써줘야 하는데, 이때는 throw 문을 통해서 예외를 발생시켰다.
4. onBindViewHolder
// MainActivity.kt override fun onBindViewHolder(holder: ViewHolder, position: Int) { val currentItem = cardList[position] when(holder.itemViewType) { MultiViewEnum.BLUE.viewType -> { val blueHolder = holder as BlueTypeViewHolder blueHolder.bind(currentItem) holder.itemView.setOnClickListener { onClick(currentItem) } } MultiViewEnum.LIGHTBLUE.viewType -> { .. } MultiViewEnum.ORANGE.viewType -> { .. } } }일단 onBindViewHolder 의 경우에는 매개변수로 position 을 받아오는데, getItemCount() 의 결과값만큼 position 을 0부터 1씩 증가하며 리턴한다. 이때, position을 받아와서 해당 리스트의 Card 클래스 객체 값을 currentItem 변수에 저장한다.
viewtype 별로 holder를 다르게 받아와주고, holder 에서 정의한 bind 함수에다가 현재 객체를 넘겨주며 화면에 리스트를 하나씩 띄우게 된다. 리사이클러뷰 아이템을 클릭했을때, 이벤트를 처리해야하는데, 이것도 onBindViewHolder 내에서 처리해주면 된다.
메인 액티비티에서 어댑터 연결
private val multiCardAdapter : MultiCardAdapter by lazy { MultiCardAdapter { card -> adapterOnClick(card) } } private fun adapterOnClick(card:Card) { //bundle로 넘기는 작업, extension 안쓰고 작업 val intent = Intent(this, DetailActivity::class.java) val bundle = Bundle().apply { putParcelable(DetailActivity.EXTRA_CARD,card) } intent.putExtras(bundle) startActivity(intent) }메인 액티비티에서는 어댑터 객체를 생성하고, 리사이클러뷰 내 아이템이 클릭됐을때 이벤트 처리를 adapterOnClick 이라는 메소드 안에다가 해주면 된다.
// DetailAcitivity.kt val cardItem = intent.getParcelableExtra<Card>(EXTRA_CARD)디테일 액티비티에서 key 값으로 Card 데이터를 받아오고
바인딩을 통해 뷰에다가 해당 데이터가 가지고 있는 값을 연결하면 데이터 전달까지 완료할 수 있다.
'Android' 카테고리의 다른 글
SharedPreferences (2) 2024.05.01 알림(Notification) (0) 2024.04.30 다이얼로그 (0) 2024.04.25 프래그먼트 생명주기 (0) 2024.04.24 개인 과제 트러블 슈팅(프래그먼트 트랜잭션) (0) 2024.04.22