[안드로이드 / Kotlin] RecyclerView Drag&Drop / Swipe 구현

2022. 3. 15. 16:32·Android
반응형

오늘은 안드로이드에서 RecyclerVIew를 사용할때 외부 라이브러리 없이 Drag&Drop으로 아이템의 위치를 변경하거나, Swipe로 아이템을 삭제하는 방법에 대해 알아보도록 하겠습니다.

 

먼저 해당 기능을 사용하기 위해 ItemTouchHelper.Callback을 상속받은 콜백 클래스 ItemTouchHelperCallback 정의합니다. 이벤트가 발생하여 콜백이 오면 필요한 정보를 전달할 인터페이스 OnItemMoveListener를 정의합니다. 해당 리스너를 편의를 위해 ItemTouchHelperCallback의 파라미터로 놓고, 아이템 움직임에 따른 onItemMoved()와 스와이프에 따른 onItemSwipe() 메소드를 각각 구현해서 사용하시면 됩니다.

 

<예시 코드>

/**
 * RecyclerView Drag&Drop / Swipe
 * Callback
 */
class ItemTouchHelperCallback(private val itemMoveListener: OnItemMoveListener): ItemTouchHelper.Callback() {

    interface OnItemMoveListener {
        fun onItemMoved(from: Int, to: Int)
        fun onItemSwiped(pos: Int)
    }

    /**
     * 이벤트 방향설정
     * (방향 flag 정의)
     */
    override fun getMovementFlags(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ): Int {
        return if(recyclerView.layoutManager is GridLayoutManager) {    // GridLayout
            val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
            val swipeFlags = 0

            makeMovementFlags(dragFlags, swipeFlags)
        } else {    // LinearLayout
            val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
            val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END

            makeMovementFlags(dragFlags, swipeFlags)
        }
    }

    /**
     * 위치변화에 따른 이벤트 확인
     */
    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        itemMoveListener.onItemMoved(viewHolder.adapterPosition, target.adapterPosition)
        return true
    }

    /**
     * Swipe 이벤트
     */
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        itemMoveListener.onItemSwiped(viewHolder.adapterPosition)
    }
}

ItemTouchHelper.Callback을 상속받게되면 3개의 함수를 구현해야합니다.

  1. getMoventFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder)
    - 각 이벤트마다(Drag? Swipe?)의 '방향 flag'를 설정하기!
  2. onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder)
    - '위치변화(Move)'에 따른 콜백!
  3. onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int)
    - 'Swipe' 이벤트 콜백!

 

 

RecyclerView에서 사용할 Adapter 클래스내에 위에서 선언한 OnItemMoveListener를 구현합니다. 구현해야할 메소드내에서 Drag&Drop 및 Swipe 시 발생해야할 아이템의 변화(notifyItem)를 구현하시면됩니다.

추가적으로 adapter와 ItemTouchHelper를 연결시켜줄 OnStartDragListener를 adapter 내부에 선언합니다. 이벤트는 터치에 의해 발생하므로 구현은 Item의 setOnTouchListener()에서 하시면 되겠습니다!

 

<예시 코드>

interface OnStartDragListener {
    fun onStart(viewHolder: RecyclerView.ViewHolder)
}

class MyAdapter: RecyclerView.Adapter<MyAdapter.ViewHolder>(),
    ItemTouchHelperCallback.OnItemMoveListener {

	..
    private lateinit var dragListener: OnStartDragListener
    ..

	@SuppressLint("ClickableViewAccessibility")
    inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(
        LayoutInflater.from(parent.context).inflate(R.layout.item_linear, parent, false)
    ) {
    	..
        init {
        	..
            container.setOnTouchListener { _, event ->
            	if(event.action == MotionEvent.ACTION_DOWN) {
                	// dragListener를 이용해 ItemTouchHelper와 연결
                	dragListener.onStart(this)
                }
            }
            ..
        }    
    }

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

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

    override fun getItemCount(): Int {
        ..
    }

    interface OnStartDragListener {
        fun onStartDrag(viewHolder: RecyclerView.ViewHolder)
    }

    fun setOnStartDragListener(listener: OnStartDragListener) {
        this.dragListener = listener
    }
	
    override fun onItemMoved(fromPosition: Int, toPosition: Int) {
        Collections.swap(items, fromPosition, toPosition)
        notifyItemMoved(fromPosition, toPosition)
    }

    override fun onItemSwiped(position: Int) {
        items.removeAt(position)
        notifyItemRemoved(position)
    }

}

 

 

마지막으로 RecyclerView와 adapter를 선언하시면서 ItemTouchHelper와 콜백을 선언한뒤 연결만 해주시면 끝입니다!

val adapter = MyAdapter()
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)

val touchHelperCallback = ItemTouchHelperCallback(adapter)
val touchHelper = ItemTouchHelper(touchHelperCallback)
touchHelper.attachToRecyclerView(recyclerView)
adapter.setOnStartDragListener(object : LinearListViewAdapter.OnStartDragListener {
    override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
        touchHelper.startDrag(viewHolder)
        touchHelepr.startSwipe(viewHolder)
    }
}

 

 


 

 

참고 : https://developer-eungb.tistory.com/27

 

[Android/Kotlin] RecyclerView Drag&Drop, Swipe 구현하기

RecyclerView의 Item 순서를 변경 - Drag & Drop, RecyclerView의 Item을 밀어서 삭제하기 - Swipe 기능을 라이브러리를 사용하지 않고 ItemTouchHelper를 통해 구현하는 방법을 정리하려고 한다. Drag & Drop 먼..

developer-eungb.tistory.com

 

반응형

'Android' 카테고리의 다른 글

[안드로이드 / Kotlin] 타이머(Timer) 구현하기  (0) 2022.03.18
[안드로이드 / Kotlin] BottomSheetDialogFragment  (0) 2022.03.16
[안드로이드 / Kotlin] 저전력 블루투스 BLE(3), 기기 연결  (0) 2022.03.15
[안드로이드 / Kotlin] 화면 전환 시 작업 처리, 구성 변경 처리(onConfigurationChanged)  (0) 2022.03.06
[안드로이드 / Kotlin] 저전력 블루투스 BLE(2), 스캔  (0) 2022.02.28
'Android' 카테고리의 다른 글
  • [안드로이드 / Kotlin] 타이머(Timer) 구현하기
  • [안드로이드 / Kotlin] BottomSheetDialogFragment
  • [안드로이드 / Kotlin] 저전력 블루투스 BLE(3), 기기 연결
  • [안드로이드 / Kotlin] 화면 전환 시 작업 처리, 구성 변경 처리(onConfigurationChanged)
서주냥
서주냥
간단한 것도 기록하는 습관을 가지자
  • 서주냥
    DroidLog
    서주냥
  • 전체
    오늘
    어제
    • 전체보기 (58)
      • 알고리즘 (12)
        • 백준 (4)
        • 프로그래머스 (5)
        • 개념 (3)
      • Android (43)
        • Compose (1)
      • Java (2)
      • Kotlin (1)
  • 링크

    • GitHub
  • 인기 글

  • 태그

    코루틴
    자바
    코틀린
    투 포인터
    최단 경로
    Coroutine Flow
    ConstraintLayout
    BLE
    FusedLocationProviderClient
    RecyclerView
    Clean Architecture
    Coroutine
    reified
    viewpager2
    벨만 포드
    안드로이드
    moshi
    debounce
    viewmodel
    백준
    뷰모델
    알고리즘
    SnackBar
    다이나믹 프로그래밍
    클린 아키텍처
    textunit
    블루투스
    이진 탐색
    Hilt
    프로그래머스
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
서주냥
[안드로이드 / Kotlin] RecyclerView Drag&Drop / Swipe 구현
상단으로

티스토리툴바