데이터를 리스트 형태로 화면에 표시하는 컨테이너 역할을 수행한다.
리사이클러뷰에 표시될 아이템 뷰를 생성하는 역할로, 사용자 데이터 리스트로부터 아이템 뷰를 만든다.
리사이클러뷰가 아이템을 화면에 표시할 때, 아이템 뷰들이 리사이클러뷰 내부에서 배치되는 형태를 관리한다.
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:orientation="vertical"
가로 또는 세로로 정렬하기 위해서 layoutManager를 지정해주어야 한다. 안그러면 화면이 보이지 않는다.
binding.rvMain.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
메인 액티비티에서 위와같이 레이아웃 매니저를 정해줄 수도 있다.
xml에 recyclerView를 집어넣는다.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_player"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
이때 주의할점은 layoutManager를 꼭 설정해줘야 한다.
xml에서 설정하지 않으면 액티비티나 프래그먼트에서 따로 설정해주는 코드를 추가해줘야 한다.
항목별 레이아웃을 만들어 준다.
item_list.xml(RecyclerView를 중첩해서 사용했다.)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="10dp"
android:layout_margin="10dp">
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="player"
android:textColor="@color/black"
android:textSize="20sp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_card"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</LinearLayout>
Adapter를 만든다.
PlayerAdapter
package com.example.recyclerview
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class PlayerAdapter(val players: List<Player>) : RecyclerView.Adapter<PlayerAdapter.ViewHolder>() {
/**
* Provide a reference to the type of views that you are using
* (custom ViewHolder).
*/
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(player: Player) {
val tvName = itemView.findViewById<TextView>(R.id.tvName)
val rv_card = itemView.findViewById<RecyclerView>(R.id.rv_card)
tvName.text = player.name
rv_card.adapter = CardAdapter(player.cards)
}
}
// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
// Create a new view, which defines the UI of the list item
val view = LayoutInflater.from(viewGroup.context)
.inflate(R.layout.player_list, viewGroup, false)
return ViewHolder(view)
}
// Replace the contents of a view (invoked by the layout manager)
override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder.bind(players[position])
}
// Return the size of your dataset (invoked by the layout manager)
override fun getItemCount() = players.size
}
MainActivity에서 리사이클러뷰와 어댑터를 연결해준다.
binding.rvPlayer.adapter = PlayerAdapter(players)
RecyclerView를 사용하다 보면 특정 position 항목만 갱신해야 될 때가 있다.
예를 들면, 클릭한 항목만 배경색을 진하게 표시하는 경우가 있다.
notifyItemChanged(position, payload)에서 payload는 어댑터의 onBindViewHolder()가 호출될 때 넘겨받는 객체이다. 쉽게 말하면 notifyItemChanged()가 호출되면 onBindViewHolder()가 호출되고, 이때 position, payload를 매개변수로 넘겨 받는다. 특정 position의 holder를 업데이트할 때 payload 값으로 구분하여 애니메이션 하거나 뷰를 업데이트할 수 있다. payload의 타입은 Any다.
오버라이딩 할 수 있는 onBindViewHolder() 는 두가지가 있다.
1. override fun onBindViewHolder(holder: ViewHolder, position: Int, payloads: MutableList)
2. override fun onBindViewHolder(viewHolder: ViewHolder, position: Int)
오버라이딩이 두 개가 있는 경우, payloads가 있을 경우 1번이 호출된다. 이때 payloads 가 없을 경우를 따로 조건문으로 걸러내서 2번을 따로 호출해줘야 한다. 2번이 그냥 호출되지는 않는다.
if (payloads.isEmpty()) {
super.onBindViewHolder(holder, position, payloads)
} else {
payloads.forEach {
if (it.toString() == "[click]") {
holder.itemView.setBackgroundColor(Color.LTGRAY)
}
}
}
super.onBindViewHolder(holder, position, payloads)
이 함수의 내부코드를 보면,
public void onBindViewHolder(@NonNull VH holder, int position,
@NonNull List<Object> payloads) {
onBindViewHolder(holder, position);
}
이 안에서 2번 함수를 호출해준다.
한 개가 있는 경우, 2번이 바로 호출된다.
메인 액티비티에서 아래처럼 payloads를 넣어주면 된다.
blockAdapter.notifyItemChanged(position, mutableListOf("click"))