[Android/Kotlin] RecyclerView 클릭 이벤트 적용하기

2021. 1. 22. 00:48📱Android/👩🏻‍💻 Android 개발 일지

반응형


RecyclerView 첫번째 시리즈에 이어 두번째 시리즈인 클릭 리스너를 추가하여 리사이클러뷰 아이템에 각각 클릭 이벤트를 적용하는 방법에 대해 적어보려고 합니다 : )

RecyclerView 만드는 방법에 대해 궁금하시다면 !? 아래 글을 먼저 읽고 와주세요!

 

[Android/Kotlin] RecyclerView 만들기

오늘은 간단한 리사이클러뷰 시리즈 1탄인 RecyclerView 만드는 방법에 대해 소개해보고자 합니다! RecyclerView 란?! RecyclerView란 ? 데이터 집합들을 각각의 개별 아이템 단위로 구성하여 화면에 출력해

yunaaaas.tistory.com

 

RecyclerView를 사용하면서 RecyclerView의 각각 아이템을 클릭하면 새로운화면으로 전환되는 것을 많이 보신 적 있을것 같습니다.

2가지의 방법을 소개해보고자 합니다.

 

1. RecyclerView Adapter에서 Click 이벤트 적용하기

2. RecyclerView가 사용되는 Activity나 Fragment에서 Click 이벤트 적용하기

 

 


1. RecyclerView Adapter에서 Click 이벤트 적용하기

📌 ProfileDetailActivity.kt 만들어주기

리사이클러뷰의 아이템을 클릭하면 전환되는 화면인 ProfileDetailActivity.kt를 하나 추가해주었습니다.

 

ProfileDetailActivity.xml

RecyclerView에서 ImageView와 TextView를 전달받아 보여줄 것이기 때문에 ImageView와 TextView를 하나씩 배치하였습니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ProfileDetailActivity">

    <ImageView
        android:id="@+id/img_profile"
        android:layout_width="200dp"
        android:layout_height="0dp"
        android:layout_marginTop="20dp"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
    
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25sp"
        android:textColor="@color/black"
        android:layout_marginTop="20dp"
        app:layout_constraintTop_toBottomOf="@id/img_profile"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
        

</androidx.constraintlayout.widget.ConstraintLayout>

 

📌Adpater ViewHolder에 클릭 이벤트 적용해주기

RecyclerView Adapter 에서 클릭이벤트를 적용하는 방법은 비교적 간단합니다 !

저번 리사이클러뷰 시리즈에서 만들었던 ProfileAdpater에 추가해주도록 하겠습니다.

RecyclerView Adpater안에 만들어놨던 InnerClass인 ViewHolder의 bind 함수 안에 추가해주시면 됩니다 : )

 

putExtra(item)으로 원하는 데이터를 ProfileDetatilActivity에 전달할 수 있습니다. 저는 Serializable을 이용하여 데이터 자체를 전달해주었습니다.

inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        private val txtName: TextView = itemView.findViewById(R.id.tv_rv_name)
        private val txtAge: TextView = itemView.findViewById(R.id.tv_rv_age)
        private val imgProfile: ImageView = itemView.findViewById(R.id.img_rv_photo)

        fun bind(item: ProfileData) {
            txtName.text = item.name
            txtAge.text = item.age.toString()
            Glide.with(itemView).load(item.img).into(imgProfile)

            itemView.setOnClickListener {
                Intent(context, ProfileDetailActivity::class.java).apply {
                    putExtra("data", item)
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                }.run { context.startActivity(this) }
            }

        }
    }

 

 

📌 ProfileDetailActivity.kt Intent로 전달받은 데이터 연결해주기

위에서 putExtra를 통해 전달한 데이터를 ProfileDetailActivity.kt에서 만들었던 ImageView와 TextView와 연결해주도록 하겠습니다.

getSerializableExtra를 통해 Intent에 같이 전달한 ProfileData를 받을 수 있습니다.

 

이때 ! 주의할 점은 putExtra("name") 과 getSerializableExtra("name")의 name이 동일해야합니다!

package com.example.recyclerview_ex

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.activity_profile_detail.*

class ProfileDetailActivity : AppCompatActivity() {
    lateinit var datas : ProfileData
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_profile_detail)

        datas = intent.getSerializableExtra("data") as ProfileData
        
        Glide.with(this).load(datas.img).into(img_profile)
        tv_name.text = datas.name
        
    }
}

 

이제 클릭이벤트를 연결한 화면을 확인해볼까요!?

아래와 같이 완성되었습니다.

 

 

2.  RecyclerView가 사용되는 Activity나 Fragment에서 Click 이벤트 적용하기

리사이클러뷰 아이템 클릭시 전환되는 화면인 ProfileDetailActivity는 위에서 구현하였으니 생략하도록 하겠습니다.

위 방법은 Item의 Position이 중요한 경우나 Adpater가 아닌 RecyclerView가 만들어진 Activity나 Fragment에서 존재하는 data를 같이 전달해야할 때 주로 사용합니다.

 

📌 ProfileAdapter.kt ClickListener Interface 만들어주기

RecyclerView에는 ListView 와 다르게 클릭리스너가 내장되어있지 않습니다! 그래서 추가로 ClickListener역할을 하는 interface를 만들어줘야합니다.

Adpater안에 OnItemClickListener 를 Interface로 만들어주고, ViewHolder에서 연결해주도록 하겠습니다.

 

Adapter Class안에 적어주시면 됩니다!

 interface OnItemClickListener{
        fun onItemClick(v:View, data: ProfileData, pos : Int)
    }
    private var listener : OnItemClickListener? = null
    fun setOnItemClickListener(listener : OnItemClickListener) {
        this.listener = listener
    }

Adapter 내부 Class인 ViewHolder bind 함수 안에 적어주시면 됩니다!

val pos = adapterPosition
if(pos!= RecyclerView.NO_POSITION)
{
       itemView.setOnClickListener {
       listener?.onItemClick(itemView,item,pos)
	 }
 }

 

ProfileAdapter.kt 전체

package com.example.recyclerview_ex

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide

class ProfileAdapter(private val context: Context) : RecyclerView.Adapter<ProfileAdapter.ViewHolder>() {

    var datas = mutableListOf<ProfileData>()

    interface OnItemClickListener{
        fun onItemClick(v:View, data: ProfileData, pos : Int)
    }
    private var listener : OnItemClickListener? = null
    fun setOnItemClickListener(listener : OnItemClickListener) {
        this.listener = listener
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder  = ViewHolder(parent.inflate(R.layout.item_recycler_ex))

     override fun getItemCount(): Int = datas.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(datas[position])
    }

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

        private val txtName: TextView = itemView.findViewById(R.id.tv_rv_name)
        private val txtAge: TextView = itemView.findViewById(R.id.tv_rv_age)
        private val imgProfile: ImageView = itemView.findViewById(R.id.img_rv_photo)

        fun bind(item: ProfileData) {
            txtName.text = item.name
            txtAge.text = item.age.toString()
            Glide.with(itemView).load(item.img).into(imgProfile)

            val pos = adapterPosition
            if(pos!= RecyclerView.NO_POSITION)
            {
                itemView.setOnClickListener {
                    listener?.onItemClick(itemView,item,pos)
                }
            }
            

        }
    }
}

 

 

📌 MainActivity에 Click 이벤트 적용해주기

ProfileAdpater 객체인 profileAdater에서 위에서 만들어준 setOnItemClickListener를 호출해줍니다. 이때 ProfileAdapter.OnItemClickListener의 Interface를 상속받아 함수를 구현해줍니다.

profileAdapter.setOnItemClickListener(object : ProfileAdapter.OnItemClickListener{
            override fun onItemClick(v: View, data: ProfileData, pos : Int) {
                Intent(this@MainActivity, ProfileDetailActivity::class.java).apply {
                    putExtra("data", data)
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                }.run { startActivity(this) }
            }

})

 

 

위와 같은 동일한 작업을 하는 화면을 만드실 수 있습니다!

RecyclerView ClickEvent를 때에 따라 사용하면 좋을 것같습니다 : )

다음 포스팅에서는 AnimationTransition을 적용한 RecyclerView에 대해 작성해보도록 하겠습니다! 

 

반응형