onClick과 LoginClick을 둘 다 사용해야하는 상황에서 구현해보고나서 정리.
Adapter 내외부 둘 다 사용이 가능하며 둘 다 반응하도록 구현했을 때는 Adapter 내부에 있는 것이 우선이었다.
1. Adapter 내부에 Interface 생성
onClick과 LongClick Interface를 생성한다.
나는 Adapter에서 ViewBinding을 사용했기 때문에 ItemAccountBinding을 받을 수 있도록 오버로딩했다. ViewBinding을 사용하지 않는 상태면 View를 받는 것만 해둬도 된다. 이걸 통해서 외부에서도 itemView에 접근할 수 있다.
interface OnClickInterface{ //OnClickListener 인터페이스
fun onClick(view: View, position: Int) //viewbinding 안했을 때
fun onClick(view: ItemAccountBinding, position: Int) //viewbinding을 적용해서 추가함.
}
interface OnLongClickInterface{ //LongClick Listener 인터페이스
fun onLongClick(view: View, position: Int) //viewbinding 안했을 때
fun onLongClick(view: ItemAccountBinding, position: Int)//viewbinding을 적용해서 추가함.
}
2. Adapter 생성자에 각 Interface Object를 받을 수 있도록 파라미터 추가
class AllAccountListAdapter(val context: Context, private val accounts:List<AccountData>,
onClick: OnClickInterface,
onLongClick: OnLongClickInterface):
RecyclerView.Adapter<AllAccountListAdapter.ItemViewHolder>(){
3. 받아온 값 선언 및 초기화
var onClickInterface: OnClickInterface = onClick
var onLongClickInterface: OnLongClickInterface = onLongClick
4. Adapter 내부에 클릭리스너 구현
둘 중에서 필요한대로 사용하면 된다. 나는 onClick을 ViewHolder에서, LongClick을 onBindViewHolder 함수에서 썼다.
4-1. ViewHolder Class에 구현
ViewHolder 클래스는 inner클래스로 구현. onBind함수 내에서 구현하였다. ViewBinding을 사용하고 있기 때문에 thisBinding이란 변수로 받아서 각각 리스너에 넣어줌.
//아이템 뷰홀더
inner class ItemViewHolder(binding: ItemAccountBinding): RecyclerView.ViewHolder(binding.root){
val accountName = binding.tvAccountName
val checkBox = binding.cbAccountCheck
val thisBinding = binding
fun onBind(context: Context, item: AccountData, itemPosition: Int){
accountName.text = item.name
//OnClickListener
itemView.setOnClickListener(View.OnClickListener {
onClickInterface.onClick(thisBinding, position = itemPosition)
//실행하고자 하는 코드 입력
})
//LongClick Listener
itemView.setOnLongClickListener(View.OnLongClickListener {
onLongClickInterface.onLongClick(it, position = itemPosition)
//실행하고자 하는 코드 입력
return@OnLongClickListener true
})
}
}
4-2. onBindViewHolder 함수 내 적용
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = accounts[position]
holder.onBind(context, item, position)
//OnClickListener
holder.itemView.setOnClickListener(View.OnClickListener {
onClickInterface.onClick(it, position)
//실행하고자 하는 코드 입력
})
//LongClick Listener
holder.itemView.setOnLongClickListener(View.OnLongClickListener {
onLongClickInterface.onLongClick(it, position)
//실행하고자 하는 코드 입력
return@OnLongClickListener true
})
}
5.Kotlin 코드 추가
이 Adapter를 이용해 구현한 RecyclerView가 있는 Kotlin 코드로 이동해서 코드를 추가해 준다.
Adapter를 생성할 때 필요한 Object를 생성해줘야한다.
val obj = object: AllAccountListAdapter.OnClickInterface {
override fun onClick(view: View, position: Int) {
//Toast.makeText(context,"온클릭",Toast.LENGTH_SHORT).show()
}
//ViewBinding으로 Adapter를 구현했기 때문에 외부에서 직접 아이템에 영향을 주려면 아래와 같이 할 수 있다.
//여기 코드에서는 아이템 명을 바꾸는 코드지만 우선순위는 내부 리스너 먼저이기에 작동하지 않음.
override fun onClick(view: ItemAccountBinding, position: Int) {
view.tvAccountName.text = "Test"
}
}
val obj2 = object: AllAccountListAdapter.OnLongClickInterface {
override fun onLongClick(view: View, position: Int) {
//Toast.makeText(context,"롱클릭",Toast.LENGTH_SHORT).show()
}
override fun onLongClick(view: ItemAccountBinding, position: Int) {
TODO("Not yet implemented")
}
}
val itemClickInterface: AllAccountListAdapter.OnClickInterface = obj
val itemLongClickInterface: AllAccountListAdapter.OnLongClickInterface = obj2
6. Adapter 생성할 때 필요한 값 넣어주기
Adapter Class 생성자에 파라미터를 추가했기 때문에 그에 맞게 넣어주면 된다.
//Adapter 생성자 부분에 위에서 생성한 object를 넣어주기
val adapter =AllAccountListAdapter(requireContext(), it, itemClickInterface, itemLongClickInterface)
'개발 공부 > Android' 카테고리의 다른 글
[Androit Kotlin] 국가 코드 가져오기 (0) | 2022.08.18 |
---|---|
[Android] TextView 줄임 표시 (ellipsize) (0) | 2022.08.11 |
[Android] RecyclerView Item Ripple Effect(리플 적용하기) (0) | 2022.08.09 |
[Android Kotlin] registerForActivityResult() 구현 (0) | 2022.08.07 |
[Android] EditText 읽기 전용으로 만들기 (0) | 2022.08.06 |