리스트뷰 그리는 방법3 : RecyclerView
리스트뷰는 유사하게 반복되는 뷰를 그리기 위한 도구이다.
리스트뷰를 그리는 방법에는 세가지가 있다.
1. addView : 실제로 리스트뷰를 그리기 위해 잘 사용되지 않는다.
2. ListView : 예전에 많이 사용되었다.
3. RecycleView : 최근에 가장 많이 사용되고있고 가장 효율이 높다.
위 세가지를 구현하는 방법 중 RecyclerView에 대해 알아본다.
RecyclerView
recyclerview는 listview의 개선판으로 Adapter를 이용하며 ViewHolder 개념을 포함한다.
recyclerview에서는 layoutmanager를 관리하여
linear, grid, staggeredgrid 등 유연하게 다양한 레이아웃을 만들 수 있다.
recyclerView를 만들기 전 app단의 build.gradle에서 recyclerview를 추가한다.
implementation "androidx.recyclerview:recyclerview:1.2.0"
XML 파일에는 recyclerview를 만든다
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AddViewActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
activity에서 RecyclerViewAdapter를 만든다.
RecyclerViewAdapter에서는 ViewHolder를 만들고 이를 상속받는다.
ViewHolder에서는 init에서 findViewById를 이용하여 뷰를 생성하고
세개의 메소드를 override한다.
- onCreateViewHolder() : 뷰를 만들어 ViewHolder에 넣어 return한다.
- getItemCout() : 아이템 리스트 사이즈를 return한다.
- onBindViewHolder() : ViewHolder의 태그를 재활용하여 holder에 있는 뷰에 그려넣어준다.
class RecyclerViewAdapter(
val itemList : ArrayList<CarForList>,
val inflater : LayoutInflater
) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val carName: TextView
val carEngine: TextView
init{
carName = itemView.findViewById(R.id.car_name)
carEngine = itemView.findViewById(R.id.car_engine)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = inflater.inflate(R.layout.item_view, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return itemList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.carName.text = itemList[position].name
holder.carEngine.text = itemList[position].engine
}
}
- onCreateViewHolder가 호출이 되면 아이템 하나가 들어갈 view를 만들어 ViewHolder에 넣어 return하고
- 호출된 ViewHolder에서 itemView로 view를 받아 만들면 findViewById를 통해 뷰를 세팅한다.
- onBindViewHolder가 호출이 되면 세팅된 뷰를 불러 값을 넣어준다.
onCreate()에서는 adapter와 layoutManager를 만들어 recyclerview에 넣어준다.
LinearLayoutManager 대신 다른 레이아웃 매니저를 넣어도 가능하다.
private lateinit var binding: ActivityRecyclerviewBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRecyclerviewBinding.inflate(layoutInflater)
setContentView(binding.root)
// 아이템 리스트 준비
val carList = ArrayList<CarForList>()
for (i in 1 .. 10){
carList.add(CarForList(""+i+"번째 자동차", ""+i+"순위 엔진"))
}
val adapter = RecyclerViewAdapter(carList, LayoutInflater.from(this@RecyclerViewActivity))
binding.recyclerviewContainer.adapter = adapter
binding.recyclerviewContainer.layoutManager = LinearLayoutManager(this@RecyclerViewActivity)
}
✔ 리스너 적용하기
ViewHolder 클래스의 init 부분에 리스너를 달아준다.
이 때, ViewHolder 클래스 밖의 클래스인 RecyclerViewAdapter의 itemList를 사용해야하기 때문에
ViewHolder 클래스를 inner class로 바꿔준다.
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val carName: TextView
val carEngine: TextView
init{
carName = itemView.findViewById(R.id.car_name)
carEngine = itemView.findViewById(R.id.car_engine)
itemView.setOnClickListener{
val position: Int = bindingAdapterPosition
val enginName = itemList[position].engine
Log.d("engine", enginName)
}
}
}
정리된 최종 activity는 다음과 같다.
package com.example.prac_android
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.prac_android.databinding.ActivityListviewBinding
import com.example.prac_android.databinding.ActivityRecyclerviewBinding
class RecyclerViewActivity : AppCompatActivity() {
private lateinit var binding: ActivityRecyclerviewBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityRecyclerviewBinding.inflate(layoutInflater)
setContentView(binding.root)
// 아이템 리스트 준비
val carList = ArrayList<CarForList>()
for (i in 1 .. 10){
carList.add(CarForList(""+i+"번째 자동차", ""+i+"순위 엔진"))
}
val adapter = RecyclerViewAdapter(carList, LayoutInflater.from(this@RecyclerViewActivity))
binding.recyclerviewContainer.adapter = adapter
binding.recyclerviewContainer.layoutManager = LinearLayoutManager(this@RecyclerViewActivity)
}
}
class RecyclerViewAdapter(
val itemList : ArrayList<CarForList>,
val inflater : LayoutInflater
) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>() {
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val carName: TextView
val carEngine: TextView
init{
carName = itemView.findViewById(R.id.car_name)
carEngine = itemView.findViewById(R.id.car_engine)
itemView.setOnClickListener{
val position: Int = bindingAdapterPosition
val enginName = itemList[position].engine
Log.d("engine", enginName)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = inflater.inflate(R.layout.item_view, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return itemList.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.carName.text = itemList[position].name
holder.carEngine.text = itemList[position].engine
}
}
'💻개발 > Android' 카테고리의 다른 글
Async (0) | 2021.05.30 |
---|---|
TabLayout과 Pager (0) | 2021.05.29 |
리스트뷰 그리는 방법2 : ListView (0) | 2021.05.28 |
리스트뷰 그리는 방법1 : addView (0) | 2021.05.28 |
Framework 와 Library (0) | 2021.05.28 |