ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] ItemTouchHelper란
    안드로이드 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
    반응형

    댓글

Designed by ZibroTistory.