0. 종속성 추가
RecyclerView
를 사용하기 위해서는 먼저 app 모듈의 build.gradle에 종속성을 추가해야 합니다.
dependencies {
implementation "androidx.recyclerview:recyclerview:1.2.1"
// For control over item selection of both touch and mouse driven selection
implementation "androidx.recyclerview:recyclerview-selection:1.1.0"
}
1. 레이아웃 파일에 RecyclerView 추가
레이아웃 파일에 RecyclerView
를 추가합니다. RecyclerView에는 width
와 height
속성 외에도 꼭 추가해야 하는 속성들이 있습니다. 먼저, orientation
속성으로 목록을 세로 방향, 혹은 가로 방향으로 표시할 수 있도록 설정할 수 있습니다.
세로 방향으로 보기 위해서는 android:orientation="vertical"
, 가로 방향으로 보기 위해서는 android:orientation="horizontal"
과 같이 속성을 추가합니다.
그 다음은 layoutManager
속성입니다. 이 속성은 리스트를 수평 혹은 수직으로 배치할 것인지(LinearLayoutManager
), 그리드 화면으로 배치(2단, 3단 진열 등)할 것인지(GridLayoutManager
), 아이템의 크기에 따라 높이나 너비가 불규칙한 그리드 화면으로 배치할 것인지(StaggeredGridLayoutManager
)를 설정할 수 있습니다.
리스트를 수평 혹은 수직으로 배치하기 위해 app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
와 같이 속성을 추가합니다.
- res/layout/activity_main.xml
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
2. RecyclerView 아이템 레이아웃 추가
RecyclerView 아이템에 표시될 아이템 레이아웃을 생성합니다. 저는 사용자들의 이름과 나이가 담겨있는 리스트를 뿌려주기 위해 TextView
두 개로 이루어진 레이아웃을 작성했습니다.
- res/layout/item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_weight="1"
tools:text="이름"/>
<TextView
android:id="@+id/tvUserAge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:layout_weight="1"
tools:text="나이"/>
</LinearLayout>
3. Adapter 작성
Adapter는 RecyclerView.Adapter
를 상속받아 구현하고, ViewHolder는 RecyclerView.ViewHolder
를 상속받아 구현합니다.
먼저 ViewHolder를 구현합니다. ViewHolder는 우리가 만든 데이터를 실제 레이아웃의 데이터로 연결시키는 기능을 합니다.
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
var datas = mutableListOf<User>()
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvUserName: TextView = itemView.findViewById(R.id.tvUserName)
val tvUserAge: TextView = itemView.findViewById(R.id.tvUserAge)
// View와 데이터를 연결시키는 함수
fun bind(item: User) {
tvUserName.text = item.userName
tvUserAge.text = item.userAge.toString()
}
}
...
}
그 다음에 구현할 Adapter에는 ViewHolder에 담길 데이터들, 데이터들과 레이아웃을 묶을 수 있게 레이아웃을 inflate할 수 있는 함수 등이 있어야 합니다. 해당 부분들은 RecyclerView.Adapter
제너릭 클래스에 존재하기 때문에 이를 상속받으면 됩니다.
- RecyclerAdapter.kt
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
...
// 데이터와 레이아웃을 묶을 수 있게 레이아웃을 inflate하는 함수
// viewGroup의 context를 사용하여 특정 화면에서 구현할 수 있도록 함
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_user, parent, false))
}
// ViewHolder에서 데이터 묶는 함수가 실행되는 곳
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(datas[position])
}
override fun getItemCount() = datas.size
}
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
var datas = mutableListOf<User>()
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvUserName: TextView = itemView.findViewById(R.id.tvUserName)
val tvUserAge: TextView = itemView.findViewById(R.id.tvUserAge)
fun bind(item: User) {
tvUserName.text = item.userName
tvUserAge.text = item.userAge.toString()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
: RecyclerAdapter.ViewHolder {
return ViewHolder(LayoutInflater.from(parent.context)
.inflate(R.layout.item_user, parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(datas[position])
}
override fun getItemCount(): Int = datas.size
}
4. Adapter와 RecyclerView 연결
- MainActivity.kt
class MainActivity : AppCompatActivity() {
private val rvUserRecyclerView : RecyclerView by lazy {
findViewById(R.id.rvUserRecyclerView)
}
private lateinit var RecyclerAdapter: RecyclerAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val userList: MutableList<User> = mutableListOf(
User("테스트1", 20),
User("테스트2", 25),
User("테스트3", 42),
User("테스트4", 66)
) // 임의로 생성한 데이터
RecyclerAdapter = RecyclerAdapter(this)
// Adapter 생성
RecyclerAdapter.datas = userList
// 테스트 데이터 리스트를 Adapter에 담고
rvUserRecyclerView.adapter = RecyclerAdapter
// 생성한 Adapter를 activity_main에 만들어둔 RecyclerView에 연결
}
}
만약 리스트에 데이터를 추가하는 경우에는 RecyclerAdapter의 datas에 데이터를 추가한 후에 notifyDataSetChanged()
혹은
notifyItemInserted(position)
, notifyItemRangeChanged(positionStart, itemCount)
를 통해 RecyclerView를 업데이트할 수 있습니다.
💡 RecyclerView에 데이터를 추가할 경우
✔️ notifyDataSetChanged()
ㄴ 리스트의 크기와 아이템 모두 변경되는 경우에 사용합니다.
✔️ notifyItemInserted(position: Int)
ㄴ 어느 특정 위치(position)에 아이템을 추가 할 때 사용합니다.
✔️ notifyItemRangeChanged(positionStart, itemCount)
ㄴ 어느 특정한 위치(positionStart)부터 연속된 여러 개의 아이템을 추가할 때 사용합니다.
ㄴ 추가할 아이템의 개수를 itemCount라는 변수로 지정해야 합니다.
5. 완성된 화면
개인적으로 데이터를 삭제/추가/수정함에 따라 RecyclerView가 업데이트되는 부분을 더 추가하였습니다.
그 외
완성 코드
https://github.com/na-ram/AOS_RecyclerView_Example.git
자료 참조
'Programando > Android' 카테고리의 다른 글
[Android/Kotlin] ViewBinding (0) | 2022.01.27 |
---|---|
[Android/Kotlin] Retrofit2를 통해 RestAPI와 통신하기 (2) | 2022.01.13 |
[Android/Kotlin] 안드로이드 숫자 국가 코드 (0) | 2021.11.12 |
[Android/Kotlin] Retrofit2 PHP MySQL 통신 (0) | 2021.09.13 |
[Android/Kotlin] ViewPager2, Remote Config_(7) (0) | 2021.08.21 |