공부블로그

[Kotlin] : Fragment안에 있는 리사이클러뷰에 클릭리스너 만들기 본문

코틀린

[Kotlin] : Fragment안에 있는 리사이클러뷰에 클릭리스너 만들기

떠어영 2022. 2. 19. 01:25

내가 아는 방식은 아이템뷰에 클릭리스너를 달아주어서 바로 데이터를 가져오는 방식이었다.

 

아이템뷰는 뷰홀더안에 저장되어 있기 때문에 뷰홀더에서 클릭리스너 함수를 작성해주고,

뷰에서 바로 원하는 데이터를 가져와서 변수에 저장하는 방식이다. 

inner class Holder(val binding: ItemReportsRecyclerBinding): RecyclerView.ViewHolder(binding.root) {
        init {
            binding.cardView.setOnClickListener {

                val pos = adapterPosition
                val item = binding.idName.text
            }
        }

그런데 위처럼 작성하니까 클릭버튼 자체가 동작하지 않는 것 같아서 검색을 해봤더니

리사이클러뷰 외부에서 아이템 클릭 이벤트를 처리하는 거여서 안되는 거였다!!!

 

내가 개발하고 있는 앱은 프래그먼트에 리사이클러뷰가 올라간 방식이었다....

 

참고한 블로그는 

https://velog.io/@appletorch/%EB%A6%AC%EC%82%AC%EC%9D%B4%ED%81%B4%EB%9F%AC%EB%B7%B0-%EC%95%84%EC%9D%B4%ED%85%9C-%ED%81%B4%EB%A6%AD-%EC%9D%B4%EB%B2%A4%ED%8A%B8

 

위에 내가 알고 있던 방식은 어댑터 내부에서만 사용가능한 방법이었고,

내가 구현하고 싶었던 방식은 외부에서 아이템 클릭 이벤트를 처리하는 거였다!

 

이와 같은 상황에서는 직접 커스텀 리스너를 만들어 주는 것이 가장 쉬운 구현 방법이라고 한다.

 

우선 

1. 어댑터에 직접 리스너 인터페이스를 정의한다.

//커스텀 리스너 인터페이스 정의
interface OnItemClickListner{
    fun onItemClick(view: View, position: Int)
}

2. 인터페이스 객체를 인자로 받는 메서드와 받아온 객체를 저장할 변수도 만들어준다.

//리스너 인터페이스 객체를 전달하는 메서드 선언
fun setOnItemclickListner(onItemClickListner: OnItemClickListner){
    itemClickListner = onItemClickListner
}

//전달된 객체를 저장할 변수 정의
private lateinit var itemClickListner: OnItemClickListner

3. 뷰홀더안에 있는 아이템 클릭리스너에서 인터페이스 객체의 메서드를 호출 ( 이때 아이템뷰, position 전달 )

inner class Holder(val binding: ItemReportsRecyclerBinding): RecyclerView.ViewHolder(binding.root) {
        init {
            binding.cardView.setOnClickListener {

                val pos = adapterPosition
                if(pos != RecyclerView.NO_POSITION && itemClickListner != null){
                    itemClickListner.onItemClick(binding.cardView,pos)
                }
            }
        }
     ...
}

4. 프래그먼트에서 함수에 인터페이스 객체(object: ReportRecyclerAdapter.OnItemClickListner) 생성 및 전달 

 

4단계를 거쳐서 자식( 어댑터 )이 부모( 액티비티/프래그먼트 )의 이벤트 핸들러를 호출하는 방식이다!

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val reports = loadReportData()
        val reportRecyclerAdapter = ReportRecyclerAdapter(reports)
        binding.ReportRecyclerview.adapter = reportRecyclerAdapter
        binding.ReportRecyclerview.layoutManager = LinearLayoutManager(this.activity)
        ...
        
        val intent = Intent(this.context,ReportsDetailActivity::class.java)
        
        //메서드에 객체 전달
        reportRecyclerAdapter.setOnItemclickListner(object: ReportRecyclerAdapter.OnItemClickListner{
            override fun onItemClick(view: View, position: Int) {
                //intent.putExtra("clickedReport_username",userName)
                intent.putExtra("clickedReport_doctor", reports[position].doctor)
                intent.putExtra("clickedReport_hospital", reports[position].hospital)
                intent.putExtra("clickedReport_reportTime", reports[position].reportTime)
                intent.putExtra("clickedReport_symptom", reports[position].symptom)
                startActivity(intent)
            }
        })
    }

 

<전체코드>

class ReportsFragment : Fragment() {

		override fun onCreateView(){ ... }
        
	    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        
        val reports = loadReportData()
        //어댑터 생성
        val reportRecyclerAdapter = ReportRecyclerAdapter(reports)
        binding.ReportRecyclerview.adapter = reportRecyclerAdapter
        binding.ReportRecyclerview.layoutManager = LinearLayoutManager(this.activity)
        
        val intent = Intent(this.context,ReportsDetailActivity::class.java)
        
        //어댑터 안의 아이템 클릭 리스너
        reportRecyclerAdapter.setOnItemclickListner(object: ReportRecyclerAdapter.OnItemClickListner{
            override fun onItemClick(view: View, position: Int) {
                //intent.putExtra("clickedReport_username",userName)
                intent.putExtra("clickedReport_doctor", reports[position].doctor)
                intent.putExtra("clickedReport_hospital", reports[position].hospital)
                intent.putExtra("clickedReport_reportTime", reports[position].reportTime)
                intent.putExtra("clickedReport_symptom", reports[position].symptom)
                startActivity(intent) //액티비티 전환
            }
        })
    }
}

//어댑터 클래스
class ReportRecyclerAdapter(val reportData: MutableList<Reports>) : RecyclerView.Adapter<ReportRecyclerAdapter.Holder>() {
    
    //커스텀 리스너
    interface OnItemClickListner{
        fun onItemClick(view: View, position: Int)
    }
    //객체 저장 변수
    private lateinit var itemClickListner: OnItemClickListner
    
    //객체 전달 메서드
    fun setOnItemclickListner(onItemClickListner: OnItemClickListner){
        itemClickListner = onItemClickListner
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int ): ReportRecyclerAdapter.Holder {
        val binding = ItemReportsRecyclerBinding.inflate(LayoutInflater.from(parent.context),parent,false)
        return Holder(binding)
    }
    override fun onBindViewHolder(holder: ReportRecyclerAdapter.Holder, position: Int) {
        val report = reportData.get(position)
        holder.setReport(report)
    }
    override fun getItemCount() = reportData.size

    inner class Holder(val binding: ItemReportsRecyclerBinding): RecyclerView.ViewHolder(binding.root) {
        init {
            binding.cardView.setOnClickListener {

                val pos = adapterPosition
                if(pos != RecyclerView.NO_POSITION && itemClickListner != null){
                    itemClickListner.onItemClick(binding.cardView,pos)
                }
            }
        }
        fun setReport(report: Reports){
            ...
        }
    }
}

'코틀린' 카테고리의 다른 글

Kotlin 리사이클러 뷰( RecyclerView )  (0) 2021.11.30
Kotlin 기초 문법 (자료형)  (0) 2021.10.01