๊ตฌ๊ธ์์ ์ ๊ณตํ๋ ๊ต์ก์๋ฃ๋ฅผ ์ ๋ฆฌํ๊ธฐ ์ํ ํฌ์คํธ์ ๋๋ค.
onBindViewHolder()
๋ View์ ์๋ก์ด ๊ฐ์ผ๋ก ๋ฐ์ธ๋ฉ ํ ๋ค์ list์ ์ฌ ์
๋ ฅํฉ๋๋ค.class NumberListAdapter(var data: List<Int>):
RecyclerView.Adapter<NumberListAdapter.IntViewHolder>() {
class IntViewHolder(val row: View): RecyclerView.ViewHolder(row) {
val textView = row.findViewById<TextView>(R.id.number)
}
onCreateViewHolder()
๋ฅผ ํตํด ๋ ์ด์์์ inflate ํฉ๋๋ค.
onBindViewHolder()
๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ bind ํฉ๋๋ค.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
IntViewHolder {
val layout = LayoutInflater.from(parent.context)
.inflate(R.layout.item_view, parent, false)
return IntViewHolder(layout)
}
override fun onBindViewHolder(holder: IntViewHolder, position: Int) {
holder.textView.text = data.get(position).toString()
}
Activity์์ RecyclerView์ adapter๋ฅผ ์ค์ ํฉ๋๋ค.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rv: RecyclerView = findViewById(R.id.rv)
rv.layoutManager = LinearLayoutManager(this)
rv.adapter = NumberListAdapter(IntRange(0,100).toList())
}
ViewHolder๊ฐ ์์ฑ๋ ๋ ํด๋ฆญ ๋ฆฌ์ค๋๋ฅผ ์ค์ ํด์ค๋๋ค.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IntViewHolder{
val layout = LayoutInflater.from(parent.context).inflate(R.layout.item_view,
parent, false)
val holder = IntViewHolder(layout)
holder.row.setOnClickListener {
// Do something on click
}
return holder
}
RecyclerView.Adapter<ViewHolder>
๋์ ListAdapter<Int, ViewHolder>
๋ฅผ extend ํฉ๋๋ค.
list ๋น๊ต ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ๋ DiffUtil.ItemCallback
์ ์ ๋ฌํฉ๋๋ค.
class NumberListAdapter: ListAdapter<Int,
NumberListAdapter.IntViewHolder>(RowItemDiffCallback()) {
class IntViewHolder(val row: View):RecyclerView.ViewHolder(row) {
val textView = row.findViewById<TextView>(R.id.number)
}
...
ํ์ฌ list๋ฅผ ๋ค๋ฅธ list๋ก ๋ณํํ๋๋ฐ ํ์ํ ๋ฐฉ์์ ๊ฒฐ์ ํฉ๋๋ค.
class RowItemDiffCallback : DiffUtil.ItemCallback<Int>() {
override fun areItemsTheSame(oldItem: Int, newItem: Int): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Int, newItem: Int): Boolean {
return oldItem == newItem
}
}
class IntViewHolder private constructor(val binding: ItemViewBinding):
RecyclerView.ViewHolder(binding.root) {
companion object {
fun from(parent: ViewGroup): IntViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ItemViewBinding.inflate(layoutInflater,
parent, false)
return IntViewHolder(binding)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
IntViewHolder {
return IntViewHolder.from(parent)
}
override fun onBindViewHolder(holder: NumberListAdapter.IntViewHolder,
position: Int) {
holder.binding.num = getItem(position)
}
XML ์์ฑ์ ํจ์๋ฅผ ๋งคํํ ์ ์์ต๋๋ค.
๊ธฐ์กด ํ๋ ์์ํฌ ๋์.
android:text = "foo" โ TextView.setText("foo") is called
Custom ์์ฑ ์์ฑ.
app:base2Number = "5" โ TextView.setBase2Number("5") is called
Custom ์์ฑ์ ์ฌ์ฉํ์ฌ ์ถ๊ฐํฉ๋๋ค.
<TextView
android:id="@+id/base2_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
app:base2Number="@{num}"/>
binding adapter๋ฅผ ์ ์ํฉ๋๋ค.
@BindingAdapter("base2Number")
fun TextView.setBase2Number(item: Int) {
text = Integer.toBinaryString(item)
}
BindingAdapter๋ฅผ ํตํด ์ด๋ฏธ์ง ๋ก๋ ๋๋ ์๊ฐ์ ์๋ชจํ๋ ์ฒ๋ฆฌ๊ฐ ์์ ๋ executePendingBindings()
๋ฅผ ํธ์ถํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
override fun onBindViewHolder(holder: NumberListAdapter.IntViewHolder,
position: Int) {
holder.binding.num = getItem(position)
holder.binding.executePendingBindings()
}
getItemViewType()
ํจ์๋ฅผ ์ฌ์ ์ํฉ๋๋ค.onCreateViewHolder()
, onBindViewHolder
์ ์กฐ๊ฑด์ ์ถ๊ฐํ์ฌ ์ ์ ํ์ ์ฒ๋ฆฌํฉ๋๋ค.<layout ...>
<data>
<variable
name="color"
type="android.graphics.Color" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout ...>
<TextView
...
android:backgroundColor="@{color.toArgb()}" />
<TextView
...
android:text="@{color.toString()}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
adapter์์ ๋ ๊ฐ์ง ์ ํ์ ๋ํด ์์์ผ ํฉ๋๋ค.
enum class ITEM_VIEW_TYPE { NUMBER, COLOR }
getItemViewType()
์ ์์ ํ์ฌ ์ ์ ํ ์ ํ์ ๋ฐํํฉ๋๋ค.
override fun getItemViewType(position: Int): Int
override fun getItemViewType(position: Int): Int {
return when(getItem(position)) {
is Int -> ITEM_VIEW_TYPE.NUMBER.ordinal
else -> ITEM_VIEW_TYPE.COLOR.ordinal
}
}
class ColorViewHolder private constructor(val binding: ColorItemViewBinding):
RecyclerView.ViewHolder(binding.root) {
companion object {
fun from(parent: ViewGroup): ColorViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = ColorItemViewBinding.inflate(layoutInflater,
parent, false)
return ColorViewHolder(binding)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int):
RecyclerView.ViewHolder {
return when(viewType) {
ITEM_VIEW_TYPE.NUMBER.ordinal -> IntViewHolder.from(parent)
else -> ColorViewHolder.from(parent)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is IntViewHolder -> {
holder.binding.num = getItem(position) as Int
holder.binding.executePendingBindings()
}
is ColorViewHolder -> {
holder.binding.color = getItem(position) as Color
holder.binding.executePendingBindings()
}
}
}
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = GridLayoutManager(this, 2)
SpanSizeLookup ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ getSpanSize(position)
์ฌ์ ์ํฉ๋๋ค.
val manager = GridLayoutManager(this, 2)
manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return when (position) {
0,1,2 -> 2
else -> 1
}
}
}