오늘 RecyclerView에서 아이템을 클릭했을 때 Context Menu를 보이고 아이템을 삭제를 해주고 싶었는데 생각보다 구현하기가 어려워서 블로그에 기록하기로 마음을 먹었습니다.
제가 어려웠던 부분은 Context Menu를 띄웠는데 삭제 메뉴를 누르면 NullPointerException
에러가 뜨고 이 오류를 해결해도 아이템이 그대로 있었습니다.
구글 검색을 통해 RecyclerView는 ViewHolder안에서 View.OnCreateContextMenuListener
인터페이스를 추가해 onCreateContextMenu
메서드를 구현해줘야 한다는 사실을 알았습니다. 다행히 이 힌트를 얻고 제가 원하는 기능을 구현할 수 있게 되었고 제가 이 힌트를 얻기 전에는 ViewHolder 밖에서 구현해 줘서 아무 변화가 없었던 거 같아요.
사용자가 특정 항목이나 뷰를 길게 클릭할 때 나타나는 메뉴입니다. 카카오톡 채팅방을 길게 누르면 채팅방 이름 설정, 채팅방 상단 고정 등 메뉴가 뜨는데
이게 바로 Context Menu입니다.
res -> menu -> conntext_menu.xml (menu 폴더 New Resoure Directiry로 생성합니다. )
menu 안에 item을 만들어줍니다.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/itemDelete"
android:title="항목삭제" />
</menu>
View.OnCreateContextMenuListener
를 인터페이스를 추가해 콜백 메서드인 onCreateContextMenu
를 구현해줍니다. findItem으로 itemDelete을 찾습니다.
그리고 아이템에 대한 클릭 리스너를 설정하고 { } 안에서 클릭 이벤트가 발생했을 때 부분이 구현됩니다.adapterPosition으로 현재 ViewHolder의 위치를 position 변수에 저장
을 먼저 하고RecyclerView.NO_POSITION
는 유효하지 않은 상숫값 -1이 들어갑니다. 아이템의 위치가 유효하지 않을 때 이 값으로 설정됩니다.해당 위치의 아이템이 삭제되었음을 알립니다.
inner class AdapterViewHolder(binding: ItemInfoBinding) :
RecyclerView.ViewHolder(binding.root), View.OnCreateContextMenuListener {
val nameTextView: TextView = binding.nameTextView
val ageTextView: TextView = binding.ageTextView
val korTextView: TextView = binding.korScoreTextView
init {
itemView.setOnCreateContextMenuListener(this)
}
override fun onCreateContextMenu(
menu: ContextMenu?,
v: View?,
menuInfo: ContextMenu.ContextMenuInfo?
) {
menu?.setHeaderTitle(studentList[adapterPosition].name)
menuInflater.inflate(R.menu.context_menu, menu)
menu?.findItem(R.id.itemDelete)?.setOnMenuItemClickListener {
val position = adapterPosition
if (position != RecyclerView.NO_POSITION) {
studentList.removeAt(position)
notifyItemRemoved(position)
}
true
}
}
}
참고사이트
1. https://velog.io/@pass/Context-Menu
2. https://developer.android.com/guide/topics/ui/menus?hl=ko
3. https://velog.io/@chhue/Menu