https://velog.io/@sjlim/Andorid-UMC-Study-3%EC%A3%BC%EC%B0%A8
마지막 장 ListView 참조!
화면안에 들어갈 한정된 수의 뷰를 유지함으로써 매우 효율적으로 스크롤 할 수 있음
리스트뷰와 다르게 재활용이 가능한 뷰
아래로 스크롤 할때마다 맨위에 존재하는 뷰객체를 아래쪽에 나타날 뷰 위치로 객체를 이동시키는 즉, 재사용하는 하는 동작 방식
이때 맨 처음 뷰객체를 기억하고 있을 뷰홀더가 필요하고 어댑터와 레이아웃매니저가 필요
1) LayoutManager
ex) LinearLyaoutManager
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
// context, 방향(가로/세로), reverse layout 여부
2) Adapter
onCreateViewHolder : ViewHolder 생성하여 반환
onBindViewHolder : ViewHoler에 값을 설정
getItemcount : 아이템의 개수 반환
3) ViewHolder
4) 데이터 리스트 예제
data class Album (
var title: String? = "",
var singer: String? = "",
var coverImg: Int? = null,
var songs: ArrayList<Song>? = null
)
private var albumDatas = ArrayList<Album>();
albumDatas.apply {
add(Album("Butter", "방탄소년단 (BTS)", R.drawable.img_album_exp))
add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2))
add(Album("Next Level", "에스파 (AESPA)", R.drawable.img_album_exp5))
add(Album("Boy with Luv", "방탄소년단(BTS)", R.drawable.img_album_exp3))
add(Album("City", "오왼 (Owen)", R.drawable.img_album_exp6))
add(Album("고해", "오왼 (Owen)", R.drawable.img_album_exp4))
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_marginLeft="10dp"
android:layout_marginRight="10dp">
<androidx.cardview.widget.CardView
android:id="@+id/item_album_cover_img_cv"
android:layout_width="150dp"
android:layout_height="150dp"
app:cardCornerRadius="7dp"
app:cardElevation="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/item_album_cover_iv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/img_album_exp2"
android:scaleType="fitCenter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.cardview.widget.CardView>
<ImageView
android:id="@+id/item_album_play_iv"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="5dp"
android:src="@drawable/widget_black_play"
app:layout_constraintBottom_toBottomOf="@id/item_album_cover_img_cv"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/item_album_title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LILAC"
android:textSize="20sp"
android:textColor="@color/black"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/item_album_cover_img_cv"/>
<TextView
android:id="@+id/item_album_singer_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="아이유 (IU)"
android:textSize="15sp"
android:layout_marginTop="3dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/item_album_title_tv"/>
</androidx.constraintlayout.widget.ConstraintLayout>
binding.homeTodayAlbumRv.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
class AlbumRVAdapter(private val albumList: ArrayList<Album>) :
RecyclerView.Adapter<AlbumRVAdapter.ViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AlbumRVAdapter.ViewHolder {
val binding: ItemAlbumBinding = ItemAlbumBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup,false)
return ViewHolder(binding)
}
// 아이템 뷰 홀더에 데이터 바인딩
override fun onBindViewHolder(holder: AlbumRVAdapter.ViewHolder, position: Int) {
holder.bind(albumList[position])
}
// data set 크기를 알려주는 함수 => 리사이클러뷰의 마지막이 어디인지 알 수 있음
override fun getItemCount(): Int = albumList.size
// ViewHolder, inner class로 생성
inner class ViewHolder(val binding: ItemAlbumBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(album : Album) {
binding.itemAlbumTitleTv.text = album.title
binding.itemAlbumSingerTv.text = album.singer
binding.itemAlbumCoverIv.setImageResource(album.coverImg!!)
}
}
}
// 어댑터 설정
val albumRVAdapter = AlbumRVAdapter(albumDatas)
// rv와 adapter 연결
binding.homeTodayAlbumRv.adapter = albumRVAdapter
5) RecyclerView에서의 Click Listener
// step 1
interface MyItemClickListener{
fun onItemClick(album : Album)
fun onRemoveAlbum(position: Int)
}
// listener 객체 전달 받는 함수 & 저장하는 변수
private lateinit var mItemClickListener: LockerSaveRVAdapter.MyItemClickListener
fun setMyItemClickListener(itemClickListener: LockerSaveRVAdapter.MyItemClickListener){
mItemClickListener = itemClickListener
}
fun removeItem(position: Int) {
albumList.removeAt(position)
notifyDataSetChanged()
}
// step 2
holder.itemView.setOnClickListener {
mItemClickListener.onItemClick(albumList[position])
}
holder.binding.itemSaveMoreIb.setOnClickListener {
mItemClickListener.onRemoveAlbum(position)
}
// step 3
saveRVAdapter.setMyItemClickListener(object: LockerSaveRVAdapter.MyItemClickListener{
override fun onItemClick(album: Album) {
}
override fun onRemoveAlbum(position: Int) {
saveRVAdapter.removeItem(position)
}
})
more 버튼 클릭하면 data 삭제되게 구현!