안드로이드

[Android] ItemTouchHelper란

Zibro 2022. 3. 11. 16:07
728x90
반응형

ItemTouchHelper란🤷🏻‍♂️

ItemTouchHelper는 RecyclerView에 삭제를 위한 스와이프 및 드래그 앤 드롭을 지원하는 유틸리티 클래스입니다.

ItemTouchHelper는 사용자가 액션을 수행할 때 이벤트를 수신하는 RecyclerView 및 이벤트에 반응하는 콜백 메서드가 선언되어있는 Callback 클래스와 함께 사용합니다.

 

즉, 구조적으로 RecyclerView와 ItemTouchHelper.Callback을 ItemTouchHelper가 연결시켜주는 것입니다.

 

주요 메소드

  • attachToRecyclerView(RecyclerView) : ItemTouchHelper를 제공된 RecyclerView에 붙입니다.

 

ItemTouchHelper.Callback

이 클래스는 앱과 ItemTouchHelper 사이의 계약에 해당하는 클래스입니다. ItemCallback클래스는 각 ViewHolder에 대해 어떠한 터치 행동이 가능한지 제어하고, 사용자가 정의한 액션을 수행할 때 콜백을 받습니다.

 

주요 메서드

  • getMovementFlags(RecyclerView, ViewHolder) : 각각의 뷰에 수행할 수 있는 작업을 컨트롤하기 위해서는, getMovementFlags(RecyclerView, ViewHolder) 메서드를 오버라이드하고 적절한 방향을 반환해야 합니다. makeMovementFlags(Int,Int)를 사용하여 쉽게 구성할 수도 있습니다. 또는 SimpleCallback을 사용할 수 있습니다.
  • onMove(RecyclerView, dragged, target) : 만약 사용자가 Item을 Drag한다면, ItemTouchHelper는 onMove를 호출합니다. 이 콜백 메소드를 받으면 Adapter에서 Item을 이전 위치(dragged.getAdapterPosition())에서 새로운 위치(target.getAdapterPosition())로 이동해야 하고, RecyclerView의 Adapter에서 notifyItemMoved(Int, Int)를 호출해야 합니다.
  • onSwiped(ViewHolder, Int) : View가 Swipe 되면 ItemTouchHelper는 범위를 벗어날 때까지 View를 애니메이션화한 다음 이 메서드를 호출합니다. 여기서 어댑터를 업데이트해야 하고 관련된 Adapter의 notify이벤트를 호출해야 합니다.

예제🔥

ItemTouchHelperListener

RecyclerViewAdapter와 ItemTouchHelper.Callback을 연결시켜주는 리스너입니다.

interface ItemTouchHelperListener {
    fun onItemMove(from : Int,to:Int) : Boolean
    fun onItemSwipe(position:Int)
}

RecyclerView의 Item이 Drag 되거나 Swipe 될 때 호출되는 메서드를 가진 인터페이스입니다.

 

ItemTouchHelperCallback

class ItemTouchHelperCallback(private val listener:ItemTouchHelperListener) : ItemTouchHelper.Callback() {
    //활성화된 이동 방향을 정의하는 플래그를 반환하는 메소드
    override fun getMovementFlags(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ): Int {
        val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
        val swipeFlgs = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
        return makeMovementFlags(dragFlags,swipeFlgs)
    }

    //드래그된 Item을 새로운 위치로 옮길때 호출
    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        return listener.onItemMove(viewHolder.adapterPosition,target.adapterPosition)
    }

    //사용자에 의해 swipe될 때 호출
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        listener.onItemSwipe(viewHolder.adapterPosition)
    }
}

RecyclerViewAdapter

//RecyclerView에 뿌려줄 data리스트를 RecyclerView에 바인딩 시켜주기 위한 사전 작업이 이루어지는 객체
class RecyclerViewAdapter(private val dataList:MutableList<String>) : RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>(),ItemTouchHelperListener{
    //뷰 객체를 기억하고 있을 홀딩 객체
    class ViewHolder(view : View): RecyclerView.ViewHolder(view){
        val textview = view.findViewById<TextView>(R.id.data_text)
    }
    //ViewHolder 객체가 생성되는 함수
    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_layout,parent,false))
    }

    //생성된 ViewHolder에 데이터를 바인딩해주는 함수
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.textview.text = dataList[position]
    }

    //RecyclerView의 뿌려줄 아이템 개수
    override fun getItemCount(): Int = dataList.size

    override fun onItemMove(from: Int, to: Int) : Boolean {
        val data = dataList[from]
        //리스트 갱신
        dataList.removeAt(from)
        dataList.add(to,data)

		// from에서 to 위치로 아이템 위치 변경
        notifyItemMoved(from,to)
        return true
    }

    // 아이템 스와이프되면 호출되는 메소드
    override fun onItemSwipe(position: Int) {
        // 리스트 아이템 삭제
        dataList.removeAt(position)
        notifyItemRemoved(position)
    }
}

기존에 RecyclerView.Adapter에 ItemTouchHelperListener 리스너를 상속받아 onItemMove 메서드와 onItemSwipe 메서드를 오버라이드 해서 구현했습니다.

onItemMove 메서드는 Item이 Drag될 때 사용되는 메소드입니다. 코드는 Item 리스트에서 Drag 되는 아이템을 갱신하고 notifyItemMoved를 호출하여 Item이 새로운 위치로 변경됐음을 알립니다.

onItemSwipe 메소드는 항목이 Swipe 될 때 사용되는 메서드입니다. 코드는 Item이 Swipe 되면 그 Item을 삭제하기 위해 Item 리스트에서 해당 위치의 Item을 삭제하고 notifyItemRemoved를 호출하여 해당 위치의 Item이 삭제되었다는 것을 알립니다.

 

MainActivity

//데이터
val data = MutableList(100){
            "Item $it"
        }

recyclerView.layoutManager = LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false)
//Adapter
val adapter = RecyclerViewAdapter(data)
recyclerView.adapter = adapter

//리스너를 구현한 Adapter 클래스를 Callback 클래스의 생성자로 지정
val itemTouchHelperCallback = ItemTouchHelperCallback(adapter)

//ItemTouchHelper의 생성자로 ItemTouchHelper.Callback 객체 설정
val helper = ItemTouchHelper(itemTouchHelperCallback)

//RecyclerView에 ItemTouchHelper 연결
helper.attachToRecyclerView(recyclerView)

ItemTouchHelper.Callback 객체를 ItemTouchHelper 클래스의 생성자로 넣어서 주어진 콜백 클래스로 동작하는 ItemTouchHelper 객체를 생성합니다. ItemTouchHelper.attachToRecyclerView(Recyclerview) 메서드로 RecyclerView와 연결해주시면 됩니다.

 

동작 화면🔍

 

출처👍🏻
https://velog.io/@changhee09/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-ItemTouchHelper
반응형
728x90
반응형