안드로이드 리싸이클러뷰 아이템을 클릭했을 때 화면을 이동한다던지 배경색을 바꾼다던지하는 클릭 이벤트를 처리해야할 때가 많다.
예를 들어 리싸이클러뷰 아이템을 클릭 시 화면을 이동해야하는 경우에 대해 살펴보자.
interface ItemClickListener {
fun moveRecordDetail(pamphletId : Long, view : View)
}
intereface로 Click 이벤트를 받으면 실행할 콜백 함수를 만들어주었다. id 값은 어떤 아이템을 클릭했는지 판별하는데 사용하고 view는 Navigation의 findNavController에 사용된다.
class MyRecordAdapter(private val context : Context, private val myRecordViewModel: MyRecordViewModel) : ListAdapter<PamphletItem, MyRecordAdapter.MyRecordViewHolder>(MyRecordDiffUtil()) {
var itemClickListener: ItemClickListener? = null
inner class MyRecordViewHolder(private val binding : ItemMyRecordBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item : PamphletItem) {
// 여행 중인 경우
if (!item.isFinish) {
setItem(item)
binding.tvItemMyRecordCreateTime.visibility = View.VISIBLE
binding.btnMyRecordComplte.visibility = View.VISIBLE
}
// 여행 완료 인 경우
else {
setItem(item)
binding.tvItemMyRecordCreateTime.visibility = View.VISIBLE
binding.btnMyRecordComplte.visibility = View.GONE
}
binding.btnMyRecordComplte.setOnClickListener {
myRecordViewModel.finishTravelPamphlet(item.pamphletId, item)
}
binding.ivMyRecordPamphlet.setOnClickListener {
moveDetailFragment(item.pamphletId)
}
}
private fun setItem(item : PamphletItem){
binding.tvMyRecordTitle.text = item.title
val imageUrl = item.repreImgUrl
Glide.with(context)
.load(imageUrl)
.transform(CenterCrop(), RoundedCorners(30))
.placeholder(R.drawable.background_pamphlet)
.into(binding.ivMyRecordPamphlet)
binding.tvItemMyRecordCreateTime.text = item.createTime
}
private fun moveDetailFragment(pamphletId : Long) {
val position = bindingAdapterPosition
if (position != RecyclerView.NO_POSITION) {
itemClickListener?.moveRecordDetail(pamphletId, itemView)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecordViewHolder {
val binding = ItemMyRecordBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyRecordViewHolder(binding)
}
override fun onBindViewHolder(holder: MyRecordViewHolder, position: Int) {
holder.bind(getItem(position))
}
}
리싸이클러뷰 어댑터에서 itemClickListener 인스턴스를 null로 초기화한다.
viewHolder 클래스의 moveDetailFragment에서 아이템 클릭 이벤트가 발생했을 때 itemClickListener의 move함수를 호출한다.
class MainMyRecordFragment : Fragment(), ItemClickListener {
private lateinit var adapter : MyRecordAdapter
private fun setAdapterInit() {
Log.d(TAG, "setAdapterInit: 호출됨")
adapter = MyRecordAdapter(requireContext(), myRecordViewModel).apply {
itemClickListener = this@MainMyRecordFragment
}
binding.rvMyRecord.adapter = adapter
}
override fun moveRecordDetail(pamphletId: Long, view: View) {
val bundle = bundleOf("pamphletId" to pamphletId)
Navigation.findNavController(view).navigate(R.id.action_mainMyRecordFragment_to_myRecordDetail, bundle)
}
}
리싸이클러뷰 adapter를 붙혀줄 fragment에서는 ItemClickListener 인터페이스를 상속받고 구현체 함수를 구현한다.
adapter를 초기화할 때는
itemClickListener = this@MainMyRecordFragment
를 통해
MyRecordAdapter의 itemClickListener 인스턴스에 this@MainMyRecordFragment를 할당한다.