안드로이드 - 리싸이클러뷰 ItemClickListener

이우건·2024년 2월 19일
0

안드로이드

목록 보기
14/20

안드로이드 리싸이클러뷰 아이템을 클릭했을 때 화면을 이동한다던지 배경색을 바꾼다던지하는 클릭 이벤트를 처리해야할 때가 많다.

예를 들어 리싸이클러뷰 아이템을 클릭 시 화면을 이동해야하는 경우에 대해 살펴보자.

ItemClickListener Interface

interface ItemClickListener {
    fun moveRecordDetail(pamphletId : Long, view : View)
}

intereface로 Click 이벤트를 받으면 실행할 콜백 함수를 만들어주었다. id 값은 어떤 아이템을 클릭했는지 판별하는데 사용하고 view는 Navigation의 findNavController에 사용된다.

리싸이클러뷰 adapter.kt

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함수를 호출한다.

fragment.kt

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를 할당한다.

profile
머리가 나쁘면 기록이라도 잘하자

0개의 댓글