이번 포스팅은 RecyclerView 만들기 글에 이어서 RecyclerView의 아이템 클릭 이벤트를 추가하는 방법에 대해서 이야기 합니다.

예제는 RecyclerView 만들기에서 만들었던 앱을 기반으로 진행합니다.

ViewHolder에 OnClickListener 추가하기

RecyclerView에서 아이템을 보여주는데 사용하는 것이 ViewHolder 내부에 있는 View입니다. 그렇기 때문에 아이템을 클릭하는 이벤트를 ViewHolder 내부에 있는 View에 추가하면 됩니다.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MarvelMovieViewHolder {
    return MarvelMovieViewHolder(parent).apply { 
        itemView.setOnClickListener { 
            // 클릭 이벤트 처리
        }
    }
}

onCreateViewHolder에서 ViewHolder를 만들고 apply 라는 함수를 사용해서 생성과 초기화를 동시에 작업하면 됩니다.

여기서 itemView는 ViewHolder 내부에 있는 View 입니다. 그래서 itemView에 ClickListener를 추가해 주는 코드 입니다.

클릭 이벤트를 Adapter 밖으로 전달하기

itemView에 추가한 클릭 이벤트를 Adapter 밖으로 전달하는 방법은 Interface나 higher-order function을 이용하는 것 입니다.

Adapter에 higher-order function 추가하기

class MarvelMovieAdapter : RecyclerView.Adapter<MarvelMovieAdapter.MarvelMovieViewHolder>() {
    private val items = mutableListOf<Movie>()
    var onClick: ((Movie) -> Unit)? = null
		...
}

위 코드 처럼 onClick라는 이름으로 higher-order function을 받는 변수를 추가 했습니다. onClick은 Movie를 파라미터로 전달받고 Unit을 리턴하는 형태입니다. Unit을 리턴하는 것은 리턴을 하지 않아도 되는 것과 같습니다.

ViewHolder setOnClickListener 코드

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MarvelMovieViewHolder {
    return MarvelMovieViewHolder(parent).apply {
        itemView.setOnClickListener {
            // 클릭 이벤트 처리
            val item = items[adapterPosition]
            onClick?.invoke(item)
        }
    }
}

itemView.setOnClickListener 내부에서 아이템을 가져와서 onClick 함수를 호출 할 때 전달 해 주는 코드 입니다.

item을 가져올 때 position이 필요한데 ViewHolder안에서 adapterPosition이라는 값으로 position을 가져 올 수 있습니다.

Activity에서 받아서 처리하기

movieAdapter.onClick = { item: Movie ->
    // 이벤트 처리
}

Activity가 가지고 있는 adapter에서 onClick에 람다를 추가해주면 됩니다.