huzit
___을 입력해주세요
huzit
전체 방문자
  • 분류 전체보기 (137)
    • 안드로이드(Compose) (10)
      • UI (4)
      • 개념 (6)
    • 안드로이드 (50)
      • 기본개념 (6)
      • 응용 (4)
      • Debug (18)
      • Binding (3)
      • RecyclerView (5)
      • Firebase (6)
      • Retrofit (1)
      • Activity & Fragment (4)
    • 코틀린 (22)
    • 코딩테스트 (38)
      • 백준 (10)
      • 프로그래머스 (28)
    • 일상 (6)
    • CS 지식 (4)
    • 라즈베리파이 (7)

블로그 메뉴

  • 홈
  • 태그
  • 글쓰기
  • 관리

공지사항

인기 글

태그

  • 공돌이파파
  • Java
  • 공돌카돈
  • 프로그래머스
  • Debug
  • 브레빌 밤비노 플러스
  • jetpack
  • 코틀린
  • Retrofit
  • IFTTT
  • firebase
  • docker
  • Android
  • RecyclerView
  • Kotlin
  • gts4mini
  • 라즈베리 파이
  • FCM
  • compose
  • recyclerView ClickEvent

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
huzit
안드로이드/RecyclerView

RecyclerViewItemClickEvent

RecyclerViewItemClickEvent
안드로이드/RecyclerView

RecyclerViewItemClickEvent

2022. 6. 13. 03:12
728x90

1. 리사이클 러뷰(RecyclerView) 아이템 클릭

이전 글에선 리사이클러뷰를 기본 사용법과 예제를 살펴봤습니다. 이제 리사이클 러뷰 아이템 클릭 이벤트를 처리하는 방법을 알아보겠습니다.

리스트뷰를 써본 경험이 있다면 리스트뷰의 아이템 클릭을 setOnItemClickListener()를 통해 아이템 클릭 이벤트를 처리해보셨을 겁니다.

리사이클러뷰는 리스트뷰처럼 setOnItemClickListener()와 유사한 방법을 통해 아이템 클릭이벤트를 설정할 수 없습니다.

리사이클 러뷰에선 기본적으로 제공해주는 아이템 클릭 이벤트 메서드가 없습니다.

그렇다면 리사이클러뷰에서 아이템 클릭 이벤트를 처리하는 방법은 없는 걸까요?

2. 아이템 클릭 처리주체

리스트뷰는 유사한 형태와 크기의 아이템 뷰를 한 줄로 나열합니다. 이러한 단순함으로 인해 아이템 뷰의 위치 파악하기 비교적 간단합니다.

하지만 리사이클 러뷰는, 리스트뷰에 비해 훨씬 유연하고 다양한 형태로 아이템을 표시하게 만들어줍니다.

레이아웃 매니저를 통해 아이템을 다양하게 배치할 수 있고, 애니메이션 효과를 통해 다이내믹한 화면을 구성할 수 있게 해 줍니다. 하지만 이런 장점이 이벤트 클릭 처리를 복잡하게 만드는 요인이 됩니다. 그래서 리사이클 러뷰는 아이템 클릭이벤트 리스너를 직접 다루지 않고 아이템 뷰에서 OnClickListener를 통해 처리하게 만들었습니다.

3. 구현 핵심 개념

아이템 뷰에서 OnClickListener를 통해 처리하게 만들었습니다.

위 문장을 보고 코드에서 어떻게 구현할지 바로 떠올린다면 당신은 천재입니다.

이전에 작성했던 RecyclerView란? 내용을 다시 한번 보겠습니다.

정리하자면 어댑터를 통해 만들어진 각 아이템 뷰는 뷰 홀더 객체에 저장되어 화면에 표시되고, 필요에 따라 생성 또는 재활용됩니다.

이제 머릿속에 어느 정도 코드의 형태가 그려질 것입니다.

  • 아이템 뷰에서 클릭 이벤트 처리
  • 아이템 뷰는 뷰 홀더에 저장
  • 뷰 홀더에서 클릭 이벤트 작성

따라서 아래 코드처럼 뷰 홀더가 만들어지는 시점에 클릭이벤트를 처리하면 됩니다.

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


        init {
            view.setOnClickListener {
            //TODO 코드 작성
            }
        }
    }

4. 아이템 위치 알아내기

위 내용에서 우린 클릭 이벤트를 처리할 수 있게 되었습니다. 다음에 할 일은 현재 클릭 이벤트가 발생된 아이템의 위치를 알아내는 것입니다. 보통 리사이클 러뷰에서 클릭 이벤트를 사용할 때에는 해당 아이템 뷰와 연결된 데이터를 확인, 수정, 삭제 및 선택된 아이템에 따라 다른 기능을 수행하기 위해 사용합니다. 따라서 클릭 이벤트 구현 시 가장 먼저 해야 할 일은 이벤트가 발생한 아이템의 위치를 알아내는 것입니다.

위치정보를 알아내는 것은 매우 쉽습니다.
classes.jar > androidx > recyclerview > widget > RecyclerView.java > ViewHolder에 보면

public final int getAdapterPosition() {
    if (mOwnerRecyclerView == null) {
        return NO_POSITION;
    }
    return mOwnerRecyclerView.getAdapterPositionFor(this);
}

리사이클 러뷰 자체적으로 위치를 확인할 수 있는 메서드를 제공하는 것을 알 수 있습니다.
따라서 우리는 위 코드에 대해 적절한 검사 후 사용하면 됩니다.

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

        init {
            view.setOnClickListener {
              val pos = adapterPosition
              if(pos != RecyclerView.NO_POSITION){
                  //TODO
              }
            }
        }
    }

5. 아이템 위치로 데이터 리스트 접근하기

클릭 이벤트 발생 위치를 알게 됐으니 데이터를 가져오는 것은 간단합니다.

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

        init {
            view.setOnClickListener {
              val pos = adapterPosition
                if(pos != RecyclerView.NO_POSITION){
                    val item = dataset.get(pos)
                }
            }
        }
    }

6. 리사이클 러뷰 외부에서 아이템 클릭 이벤트 처리하기

위의 경우 어댑터 내부에서만 사용 가능한 방법입니다. 위 경우 외에 액티비티, 프래그먼트에서 아이템 클릭 이벤트를 처리해야 하는 경우가 있습니다.

이런 경우 가장 쉽게 구현할 수 있는 방법은, 우리가 직접 커스텀 리스너를 만들어 주는 것입니다.
우선 1. 어댑터에 직접 리스너 인터페이스를 정의한 다음, 2. 호출할 곳에서 해당 리스너 객체를 생성하고 3. 어댑터에 전달하여 호출되도록 만드는 것입니다. 자식(여기선 어댑터)이 부모(액티비티, 프래그먼트)의 이벤트 핸들러를 호출하는 것입니다.

출처 : https://recipes4dev.tistory.com/168

1. 커스텀 리스너 인터페이스 정의

가장 먼저 해야 할 일은 어댑터 내부에 새로운 리스너를 정의하는 것입니다. 리스너에서 선언되는 메서드의 이름과 파라미터의 형식은 필요에 따라 정하면 됩니다.

class SearchCurrentAdapter(private val dataset: ArrayList<SearchData>) 
: RecyclerView.Adapter<SearchCurrentAdapter.SearchMainViewHolder>() {
    //커스텀 리스너
    interface OnItemClickListener{
        fun onItemClick(view: View, position: Int)
    }
    ...
}

2. 리스너 객체 전달 메서드와 저장할 변수 추가

외부의 객체 참조를 어댑터에 전달하는 매더스와 객체 참조를 저장하는 변수도 추가합니다.

class SearchCurrentAdapter(private val dataset: ArrayList<SearchData>) 
: RecyclerView.Adapter<SearchCurrentAdapter.SearchMainViewHolder>() {
    //커스텀 리스너
    interface OnItemClickListener{
        fun onItemClick(view: View, position: Int)
    }
    //객체 저장 변수
    private lateinit var mOnItemClickListener: OnItemClickListener
    //객체 전달 메서드
    fun setOnItemClickListener(onItemClickListener: OnItemClickListener){
        mOnItemClickListener = onItemClickListener
    }
    ...
}

3. 아이템 클릭 핸들러 메서드에서 리스너 객체 메서드 호출

어댑터 뷰 홀더에서 아이템 클릭 시 우리가 만든 커스텀 리스너의 이벤트 메서드를 호출하는 코드를 작성합니다.

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

        init {
            view.setOnClickListener {
              val pos = adapterPosition
                if(pos != RecyclerView.NO_POSITION && mOnItemClickListener != null){
                    mOnItemClickListener.onItemClick(view, pos)
                }
            }
        }
    }

4. 액티비티(또는 프래그먼트)에서 커스텀 리스너 객체 생성 및 전달

마지막으로 액티비티 또는 프래그먼트에서 커스텀 이벤트 리스너 객체를 생성하여 어댑터에 전달합니다.

class SearchCurrentActivity : AppCompatActivity() {
    companion object{
        val dataset = ArrayList<SearchData>()
    }
    private lateinit var binding: SearchActivityCurrentBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = SearchActivityCurrentBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setRecycler()
    }

    private fun setRecycler(){
        //리사이클러뷰 바인딩
        val mRecyclerView = binding.searchRecyclerCurrent
        val mSearchData = SearchData()
        //데이터 리스트에 추가
        dataset.add(mSearchData)

        val intent = Intent(applicationContext, SearchDetailActivity::class.java)
        //어댑터 생성
        val adapter = SearchCurrentAdapter(dataset)
    //클릭이벤트 호출<<<
        adapter.setOnItemClickListener(object: SearchCurrentAdapter.OnItemClickListener{
            override fun onItemClick(view: View, position: Int) {
                intent.putExtra("searchData", dataset.get(position))
                startActivity(intent)
            }
        })
    //어댑터 설정
        mRecyclerView.adapter = adapter
        mRecyclerView.layoutManager = LinearLayoutManager(applicationContext)
    }
}

adapter 코드 전문

class SearchCurrentAdapter(private val dataset: ArrayList<SearchData>) : RecyclerView.Adapter<SearchCurrentAdapter.SearchMainViewHolder>() {
    //커스텀 리스너
    interface OnItemClickListener{
        fun onItemClick(view: View, position: Int)
    }
    //객체 저장 변수
    private lateinit var mOnItemClickListener: OnItemClickListener
    //객체 전달 메서드
    fun setOnItemClickListener(onItemClickListener: OnItemClickListener){
        mOnItemClickListener = onItemClickListener
    }

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

        init {
            view.setOnClickListener {
                val pos = adapterPosition

                if(pos != RecyclerView.NO_POSITION && mOnItemClickListener != null) {

                    mOnItemClickListener.onItemClick(view, pos)
                }
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchMainViewHolder {
    ...
    }


    override fun onBindViewHolder(holder: SearchMainViewHolder, position: Int) {
        ...
    }

    override fun getItemCount(): Int = dataset.size
}

결론

위의 방법을 이용하면 간편하게 리사이클 러뷰 아이템 클릭 이벤트를 만들 수 있습니다.

출처

리사이클러뷰 클릭 이벤트

728x90
저작자표시

'안드로이드 > RecyclerView' 카테고리의 다른 글

RecyclerView의 notifyItem메서드들의 문제점을 해결해보자! 3탄(ListAdapter)  (0) 2023.03.22
RecyclerView의 notifyItem메서드들의 문제점을 해결해보자! 2탄(AsyncListDiffer)  (0) 2023.03.21
RecyclerView의 notifyItem메서드들의 문제점을 해결해보자! 1탄(DiffUtil)  (0) 2023.03.20
RecyclerView  (0) 2022.06.13
  • 1. 리사이클 러뷰(RecyclerView) 아이템 클릭
  • 2. 아이템 클릭 처리주체
  • 3. 구현 핵심 개념
  • 4. 아이템 위치 알아내기
  • 5. 아이템 위치로 데이터 리스트 접근하기
  • 6. 리사이클 러뷰 외부에서 아이템 클릭 이벤트 처리하기
  • 1. 커스텀 리스너 인터페이스 정의
  • 2. 리스너 객체 전달 메서드와 저장할 변수 추가
  • 3. 아이템 클릭 핸들러 메서드에서 리스너 객체 메서드 호출
  • 4. 액티비티(또는 프래그먼트)에서 커스텀 리스너 객체 생성 및 전달
  • 결론
  • 출처
'안드로이드/RecyclerView' 카테고리의 다른 글
  • RecyclerView의 notifyItem메서드들의 문제점을 해결해보자! 3탄(ListAdapter)
  • RecyclerView의 notifyItem메서드들의 문제점을 해결해보자! 2탄(AsyncListDiffer)
  • RecyclerView의 notifyItem메서드들의 문제점을 해결해보자! 1탄(DiffUtil)
  • RecyclerView
huzit
huzit
simple is best

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.