리스트뷰와 리사이클러뷰의 아이템 클릭 리스너
ListView에 아이템 클릭 이벤트 리스너를 넣는 것은 꽤 간단했습니다.
그냥 버튼 클릭 리스너를 다는것과 같이 setOnItemClickListener를 달아주면 되니까요
하지만 RecyclerView 안에는 어떠한 itemClickListener를 찾아볼 수 없었습니다.
이는 아이템뷰를 재사용(Recylce)하는 리사이클러뷰의 특성 때문입니다.
뷰를 재사용하기 때문에, 리스트뷰보다 적은 리소스를 사용하며, 더 유연하고 자유롭지만,
마찬가지로 뷰를 재사용하기 때문에, 아이템을 클릭했을 때 이벤트를 처리하기가 어렵다고 하네요.
하지만, 방법이 없는것은 아닙니다. 저희가 직접 아이템 클릭 리스너를 구현하여 넣어주면 되니까요.
참고로 본 포스팅에서 사용하는 리사이클러뷰 예제는 기존 포스팅에서 썼던 리사이클러뷰를 바탕으로 작성되었습니다.
https://uknowblog.tistory.com/29
리사이클러뷰 아이템 클릭 리스너 구현하기
inner class BoardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tv_time = itemView.findViewById<TextView>(R.id.tv_time)
val tv_title = itemView.findViewById<TextView>(R.id.tv_title)
val tv_name = itemView.findViewById<TextView>(R.id.tv_name)
init {
itemView.setOnClickListener {
}
}
}
사실 아이템 클릭 리스너는 그냥 ViewHolder안에서
itemView에 클릭 리스너를 넣어주면 됩니다. 참 쉽죠?
해당 아이템의 위치를 얻기 위해서는 adapterPosition 메소드를 호출하여 알 수 있습니다
하지만... 이것도 좋기는 한데 아무래도 Activity에서 setOnItemClickListener를 해주는 쪽이 더 편하겠지요?
리사이클러뷰 외부에서 ItemClickListener 달기
ViewHolder와 Adapter에서 인터페이스 정의
interface OnItemClickListener {
fun onItemClick(position: Int) {}
}
var itemClickListener: OnItemClickListener? = null
BoardAdapter.kt
먼저, OnItemClickListener 인터페이스와 onItemClick 메소드를 만들어주고,
위에서 만든 OnItemClickListener를 인스턴스화 시킵니다.
inner class BoardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tv_time = itemView.findViewById<TextView>(R.id.tv_time)
val tv_title = itemView.findViewById<TextView>(R.id.tv_title)
val tv_name = itemView.findViewById<TextView>(R.id.tv_name)
init {
itemView.setOnClickListener {
itemClickListener?.onItemClick(adapterPosition)
}
}
}
그리고 ViewHolder에서 itemClickListener의 onItemClick 메소드를 호출해줍니다.
그리고 클릭한 아이템이 몇 번째 아이템인지를 반환하는 adapterPosition 메소드를 호출해,
아이템의 position를 매개 변수로 넘겨줍니다.
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class BoardAdapter(val itemList: ArrayList<BoardItem>) :
RecyclerView.Adapter<BoardAdapter.BoardViewHolder>() {
interface OnItemClickListener {
fun onItemClick(position: Int) {}
}
var itemClickListener: OnItemClickListener? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BoardViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item_recycler_view, parent, false)
return BoardViewHolder(view)
}
override fun onBindViewHolder(holder: BoardViewHolder, position: Int) {
holder.tv_time.text = itemList[position].time
holder.tv_title.text = itemList[position].title
holder.tv_name.text = itemList[position].name
}
override fun getItemCount(): Int {
return itemList.count()
}
inner class BoardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tv_time = itemView.findViewById<TextView>(R.id.tv_time)
val tv_title = itemView.findViewById<TextView>(R.id.tv_title)
val tv_name = itemView.findViewById<TextView>(R.id.tv_name)
init {
itemView.setOnClickListener {
itemClickListener?.onItemClick(adapterPosition)
}
}
}
}
BoardAdapter.kt의 전체 코드 입니다.
액티비티에서 리사이클러뷰에 onItemClickListener set 해주기
val boardAdapter = BoardAdapter(itemList)
boardAdapter.notifyDataSetChanged()
rv_board.adapter = boardAdapter
rv_board.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
boardAdapter.itemClickListener = object : BoardAdapter.OnItemClickListener {
override fun onItemClick(position: Int) {
val item = itemList[position]
Toast.makeText(applicationContext, "${item.title} 클릭함", Toast.LENGTH_SHORT).show()
}
}
버튼에 onClickListener를 달아주듯이, boardAdapter에 위에서 정의한 onItemClickListener를 달아줍니다.
위 예제는 매개변수인 position을 사용해 내가 클릭한 아이템의 제목을 출력하는 코드입니다.
보다시피 클릭한 글의 제목을 가져온 모습이네요.
RecyclerView는 ListView처럼 기본적으로 itemClickListener를 제공하진 않지만,
직접 itemClickListener를 구현하여 아이템을 클릭했을 때 이벤트를 처리할 수 있었습니다.
해당 리스너 구현 원리와 디자인 패턴에 관해 더 알고 싶으신 분은
Strategy 패턴과 Strategy 패턴의 파생 패턴인 Template Callback Pattern,
https://uknowblog.tistory.com/343
Observer 패턴에 관한 글을 참고해주세요.
https://uknowblog.tistory.com/389
'프레임워크 > Android' 카테고리의 다른 글
안드로이드 무선디버깅 (Wireless Debugging) (0) | 2023.10.25 |
---|---|
[안드로이드] 버튼 색상 혹은 drawable이 적용되지 않는 현상 (0) | 2023.03.29 |
[안드로이드] Cause: not a valid name: 에러 해결 (0) | 2022.11.29 |
[Android/안드로이드] 지도 특정 시, 도에 색 칠하기 / 통계 지도 만들기 (1) | 2022.10.08 |
[안드로이드] Build was configured to prefer settings repositories over project repositories but repository 'Google' was added by build file 'build.gradle' 에러 (0) | 2022.07.10 |