일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- retrofit2
- #안드로이드 개발자 #안드로이드 신입 #개발자 이직 #안드로이드 면접 #신입 개발자
- retrofit
- 리사이클러뷰 체크박스
- 제플린
- zeplin
- 안드로이드 아키텍쳐
- #android #안드로이드 #glide #gif #이미지다운로드
- 레트로핏
- 빗버킷 #bitbucket #authorization failed #깃
- #안드로이드
- 메모리릭
- 안드로이드 메모리릭
- #ContentProvider #App DataShare
- #SMS API #안드로이드 SMS #SMS Retriever
- 안드로이드해상도
- 안드로이드
- 클린아키텍쳐
- #리사이클러뷰 어댑터
- 안드로이드 익명클래스
- retrofi
- MVVM
- 사용법
- 키스토어
- 구글맵안돼요
- #리사이클러뷰
- Today
- Total
땀이 삐질삐질 나는 개발 일기
[안드로이드] 기본적인 Recyclerview ViewType으로 홀더 나누기, 다른 Layout만들기 본문
안녕하세요 개발자 삐질입니다
오늘 제가 소개하고 싶은 내용은 리사이클러뷰를 다루다 보면, 칸칸이 다른 Row를 표현해야할 때가 옵니다.
그때를 위한 ViewType을 사용해 표현하는 방법 입니다.
간략하게 개념을 설명 드리겠습니다.
리사이클러뷰는 각 칸마다 해당 칸의 ViewType, 즉 해당 칸(Row"이하 칸")의 특성을 나타내는 ViewType이란 것을
기반으로 어떤 Layout을 형성할지 onCreateViewHolder에서 판단한 뒤, Holder를 return하게 됩니다.
기본적으로 이 ViewType의 Value는 개발자가 직접 지정할 수 있으며, 지정하지 않았을때는 내부적으로 Default value로 처리가 됩니다.
즉
1.빨 ViewType =1
2.주 ViewType =2
3.노 ViewType =3
4.초 ViewType =4
5.파 ViewType =5
6.남 ViewType =6
7.보 ViewType =7
과 같이 저는 ArrayList각 아이템에 ViewType을 지정하겠습니다.
리사이클러뷰는 각 칸의 데이터를 List형태로 관리하기 때문에 해당 List(샘플 데이터)를 만들기 위해
Model과 ViewType을 가지는 ItemEntity클래스를 만들어줬습니다.
ViewHolder 라는 것은 말 그대로 View를 담는 그릇입니다 RecyclerView에서는 칸칸별로 Layout을 핸들링 하기 위한 Holder를 강제하고 있습니다. ViewHolder에 대한 기본 개념은 추가적으로 공부하시기 바랍니다.
저는 기본적으로 FindViewById를 사용하지 않습니다. DataBinding을 사용해 Id에 접근합니다.
Gradle :App 에 아래와 같이 추가해주시면 됩니다.
dataBinding{
enabled= true
}
class Model {
init {
}
//각자 다른 뷰타입을 아이템 7개에 순차적으로 Insert
fun makeTestEntities(): ArrayList<Item> {
var items = ArrayList<Item>()
for (i in 1..7) {
var item =
Item(i)
items.add(item)
}
return items
}
data class Item(
var viewType: Int = 0
) {
}
}
이후 모델은 Item클래스의 객체를 7개의 List를 만들기 위한 Function을 만들어 주었습니다.
이 Function은 호출 시, 7개의 Item타입을 가지고있는 ArrayList를 반환하게 됩니다.
이후 RecyclerView Adatper를 커스텀 해주었습니다.
class ItemsAdatper(private var items: ArrayList<Model.Item>?) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
//각 뷰타입 별 분기 -> 다른 홀더와 다른 Layout을 Inflate해줌
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) {
TYPE_RE -> {
var binding =
ItemType01Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemRedHolder(
binding
)
}
TYPE_OR -> {
var binding =
ItemType02Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemOrangeHolder(
binding
)
}
TYPE_YELL -> {
var binding =
ItemType03Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemYellowHolder(
binding
)
}
TYPE_GR -> {
var binding =
ItemType04Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemGreenHolder(
binding
)
}
TYPE_BL -> {
var binding =
ItemType05Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemBlueHolder(
binding
)
}
TYPE_DEPPBL -> {
var binding =
ItemType06Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemDBlueHolder(
binding
)
}
TYPE_PU -> {
var binding =
ItemType07Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemPupleHolder(
binding
)
}
else -> {
var binding =
ItemType01Binding.inflate(LayoutInflater.from(parent.context), parent, false)
return ItemRedHolder(
binding
)
}
}
}
// 어댑터가 전달받은 리스트 사이즈 반환 , Null일땐 0
override fun getItemCount(): Int {
return items?.size ?: 0
}
//홀더 타입에 따라 뷰와 바인딩 해줌
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is ItemRedHolder) {
holder.bind(items?.get(position))
} else if (holder is ItemOrangeHolder) {
holder.bind(items?.get(position))
} else if (holder is ItemYellowHolder) {
holder.bind(items?.get(position))
} else if (holder is ItemGreenHolder) {
holder.bind(items?.get(position))
} else if (holder is ItemBlueHolder) {
holder.bind(items?.get(position))
} else if (holder is ItemDBlueHolder) {
holder.bind(items?.get(position))
} else if (holder is ItemPupleHolder) {
holder.bind(items?.get(position))
}
}
//각 아이템의 Viewtype을 반환함 여기서 반환 된 VieType-> onCreateViewHolder로 넘어감
override fun getItemViewType(position: Int): Int {
items?.let {
return it[position].viewType
} ?: kotlin.run {
return super.getItemViewType(position)
}
}
//뷰타입 종류
companion object {
const val TYPE_RE = 1;
const val TYPE_OR = 2;
const val TYPE_YELL = 3;
const val TYPE_GR = 4;
const val TYPE_BL = 5;
const val TYPE_DEPPBL = 6;
const val TYPE_PU = 7;
}
}
리사이클러뷰 어댑터에서는 기본적으로 우리가 알고있는 onCreateViewHolder / getItemCount / onBindViewHolder 외 getItemViewType이라는 Override Function을 추가로 재정의 합니다.
이 Function에는 제가 위에서 만들어 Adapter클래스로 전달해 준 ArrayList의 각 칸의 ViewType을 반환합니다.
이렇게 Model / ItemEntity / Adapter가 정의 되었다면 실제로 Recyclerview에 대한 설정을 위해 Activity에서 아래와 같이 작업 했습니다.
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
var adapter: ItemsAdatper? = null
var model: Model? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(
this,
R.layout.activity_main
)
init()
}
fun init() {
model = Model() // 데이터를 핸들링 하기 위한 Model Init
setRecyclerView() //리사이클러뷰 Init
}
fun setRecyclerView() {
adapter =
ItemsAdatper(model?.makeTestEntities())
var layoutManager = LinearLayoutManager(this)
layoutManager.orientation = RecyclerView.VERTICAL
binding.recyclerview.layoutManager = layoutManager
binding.recyclerview.adapter = adapter
}
}
참 쉽쥬?
onCreate가 호출되게 되면, inti -> setRecyclerView()를 거쳐 RecyclerView가 Adatper를 Setted하게 되고 실제 아이템을 그리게 됩니다.
예제이기 때문에 목적별 라이프사이클에 대한 Function의 위치는 무시해주세요.
그렇게 되면 아래와 같은 View를 그리게 됩니다.
이렇듯 RecyclerView는 칸칸이 다른 레이아웃(뷰홀더)을 관리할 수 있게 합니다.
-----------------------------------샘플 ItemHolder xml -----------------------------
Item_type01.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#FA0909">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="빨강색"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="40sp"></TextView>
</LinearLayout>
</layout>
Item_type02.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#F46708">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="주황색"
android:textColor="#ffffff"
android:textSize="40sp"></TextView>
</LinearLayout>
</layout>
해당 샘플의 코드는 아래 git에 가시면 볼수 있습니다.
https://github.com/jaekanglee/RecyclerViewType
'개발 Tip' 카테고리의 다른 글
[안드로이드] 아키텍쳐? 패턴 ? 처음엔 아무것도 모른다면 이것 만이라도.. (0) | 2020.04.30 |
---|---|
[안드로이드] 심심해서 찍어본 Retrofit 동기 / 비동기 Feat.Rx (0) | 2020.04.22 |
[안드로이드] 익명클래스가 메모리릭을 유발하는 EU(이유) (0) | 2020.03.12 |
[안드로이드] Recyclerview 제대로 알고 쓰자 ! (7) | 2020.03.10 |
[안드로이드] 키스토어 각종 해시값 쉽게 보는 방법 (0) | 2020.02.12 |