뷰 바인딩을 사용하여 XML 레이아웃 파일과 액티비티를 연결합니다.
RecyclerView는 안드로이드 앱에서 리스트 형태의 데이터를 표시하는데 사용되는 위젯입니다. 여러 아이템을 스크롤 가능한 리스트로 표현하며, 많은 아이템을 효율적으로 관리하고 보여주는 역할을 합니다.
binding.recycelrView.layoutManager = LinearLayoutManager(this)
true
: 순서 / false
: 역순서binding.recycelrView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false)
binding.recycelrView.layoutManager = GridLayoutManager(this,3)
binding.recycelrView.layoutManager = GridLayoutManager(this,3,GridLayoutManager.HORIZONTAL,false)
VERTICAL
: 수직 / HORIZONTAL
: 수평binding.recycelrView.layoutManager = StaggeredGridLayoutManager(3,LinearLayoutManager.VERTICAL)
findViewById
를 대체합니다.(NPE)Null Pointer Exception
이 발생하지 않습니다.Class Cast Exception
이 발생하지 않습니다.1. 의존성 추가: build.gradle
파일에 RecyclerView 의존성을 추가합니다.
implementation ("androidx.recyclerview:recyclerview:1.3.1")
gradle 설정
android{
...
// AndroidStudio 3.6 ~ 4.0
viewBinding{
enabled = true
}
// AndroidStudio 4.0 ~
buildFeatures{
viewBinding = true
}
}
// **MyAdapter.kt**
class MyAdapter(private val items: List<String>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val binding = ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int {
return items.size
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: String) {
itemView.textView.text = item
}
}
}
// MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// XML 뷰를 객체
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val items = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")
val adapter = MyAdapter(items)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this)
// ID에 접근하여 사용
binding.myButton.setOnClickListener{
binding.myTextView.text = "바인딩이 잘 되네요!"
}
}
}
// **MyAdapter.kt**
class MyAdapter(val mItems: MutableList<MyItem>) : RecyclerView.Adapter<MyAdapter.Holder>() {
interface ItemClick {
fun onClick(view : View, position : Int)
}
var itemClick : ItemClick? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val binding = ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.itemView.setOnClickListener {
itemClick?.onClick(it, position)
}
holder.iconImageView.setImageResource(mItems[position].aIcon)
holder.name.text = mItems[position].aName
holder.age.text = mItems[position].aAge
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemCount(): Int {
return mItems.size
}
inner class Holder(val binding: ItemRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root) {
val iconImageView = binding.iconItem
val name = binding.textItem1
val age = binding.textItem2
}
}
- 어댑터 객체에서 관리할 더미 데이터 객체(ArrayList)를 준비한다.
- MyAdapter 객체를 생성하고 초기화 한다.
- 생성된 MyAdapter 객체를 어댑터뷰인 리스트뷰에 연결한다.
// MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val dataList = mutableListOf<MyItem>()
dataList.add(MyItem(R.drawable.sample_0, "Bella", "1"))
dataList.add(MyItem(R.drawable.sample_1, "Charlie", "2"))
dataList.add(MyItem(R.drawable.sample_2, "Daisy", "1.5"))
dataList.add(MyItem(R.drawable.sample_3, "Duke", "1"))
dataList.add(MyItem(R.drawable.sample_4, "Max", "2"))
dataList.add(MyItem(R.drawable.sample_5, "Happy", "4"))
dataList.add(MyItem(R.drawable.sample_6, "Luna", "3"))
dataList.add(MyItem(R.drawable.sample_7, "Bob", "2"))
binding.recyclerView.adapter = MyAdapter(dataList)
// 어댑터 생성, 연결
val adapter = MyAdapter(dataList)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this) // 수직 배치
adapter.itemClick = object : MyAdapter.ItemClick {
override fun onClick(view: View, position: Int) {
val name: String = dataList[position].aName
Toast.makeText(this@MainActivity," $name 선택!", Toast.LENGTH_SHORT).show()
}
}
}
// DogItems.kt
sealed class DogItems {
data class MyItem(val aIcon:Int, val aName:String, val aAge:String) : DogItems()
data class MyTitle(val age: String) : DogItems()
}
// MyAdapter.kt
class MyAdapter(val mItems: MutableList<DogItems>) : RecyclerView.Adapter<ViewHolder>() {
companion object {
private const val VIEW_TYPE_TITLE = 1
private const val VIEW_TYPE_DOGS = 2
}
interface StickyHeader {
val stickyId: Any
}
interface ItemClick {
fun onClick(view: View, position: Int)
}
var itemClick: ItemClick? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
VIEW_TYPE_TITLE -> {
val binding =
ItemTitleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
TitleViewHolder(binding)
}
else -> {
val binding =
ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
DogViewHolder(binding)
}
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
when (val item = mItems[position]) {
is DogItems.MyTitle -> {
(holder as TitleViewHolder).title.text = "${item.age} 살"
}
is DogItems.MyItem -> {
(holder as DogViewHolder).name.text = item.aName
holder.age.text = item.aAge
holder.iconImageView.setImageResource(item.aIcon)
holder.itemView.setOnClickListener {
itemClick?.onClick(it, position)
}
}
}
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemCount(): Int {
return mItems.size
}
override fun getItemViewType(position: Int): Int {
return when (mItems[position]) {
is DogItems.MyTitle -> VIEW_TYPE_TITLE
is DogItems.MyItem -> VIEW_TYPE_DOGS
}
}
inner class TitleViewHolder(binding: ItemTitleBinding) : RecyclerView.ViewHolder(binding.root), StickyHeader {
val title = binding.tvAgetitle
override val stickyId: String
get() = (mItems[adapterPosition] as DogItems.MyTitle).age
}
inner class DogViewHolder(binding: ItemRecyclerviewBinding) :
RecyclerView.ViewHolder(binding.root) {
val iconImageView = binding.iconItem
val name = binding.textItem1
val age = binding.textItem2
}
// MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val dataList = mutableListOf(
DogItems.MyTitle("1"),
DogItems.MyItem(R.drawable.sample_3, "Duke", "1"),
DogItems.MyItem(R.drawable.sample_6, "Luna", "1"),
DogItems.MyItem(R.drawable.sample_8, "Merry", "1"),
DogItems.MyItem(R.drawable.sample_13, "mung", "1"),
DogItems.MyTitle("2"),
DogItems.MyItem(R.drawable.sample_1, "Charlie", "2"),
DogItems.MyItem(R.drawable.sample_4, "Max", "2"),
DogItems.MyItem(R.drawable.sample_7, "Bob", "2"),
DogItems.MyItem(R.drawable.sample_11, "Sara", "2"),
DogItems.MyItem(R.drawable.sample_10, "ganga", "2"),
DogItems.MyTitle("3"),
DogItems.MyItem(R.drawable.sample_5, "Happy", "3"),
DogItems.MyItem(R.drawable.sample_0, "Bella", "3"),
DogItems.MyTitle("4"),
DogItems.MyItem(R.drawable.sample_2, "Daisy", "4"),
DogItems.MyItem(R.drawable.sample_9, "Jisoo", "4"),
DogItems.MyItem(R.drawable.sample_12, "Ddong", "4")
)
val adapter = MyAdapter(dataList)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this)
// StickyHeaderDecoration
binding.recyclerView.addItemDecoration(StickyHeaderDecoration())
binding.recyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayout.VERTICAL))
adapter.itemClick = object : MyAdapter.ItemClick {
override fun onClick(view: View, position: Int) {
val name: String = (dataList[position] as DogItems.MyItem).aName
Toast.makeText(this@MainActivity," $name 선택!", Toast.LENGTH_SHORT).show()
}
}
}
}
```![](https://velog.velcdn.com/images/ouowinnie/post/4b9fe031-8792-4cf3-a700-25a7a3f3dbde/image.md)
잘 정리하셨군요! 다을님 TIL로 저도 코틀린 개념 차곡차곡 쌓아보겠씁니다~