일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- BottomNavigationView
- 개발자
- imageview
- 스플래시
- Android
- TypeConverter
- 주석
- fragment
- Gradle
- kotlin
- 테마
- 면접
- android studio
- Safe Args
- recyclerview
- Livedata
- Datastore
- Jetpack Compose
- 일렉트론
- asLiveData()
- electron
- ViewModel
- hilt
- nav_graph
- themes.xml
- 취업
- Navigation Component
- 안드로이드
- room
- Binding Adapter
- Today
- Total
나만 보는 일기장
[RecyclerView] 스와이프, 드래그&드롭 효과를 가진 RecyclerView 만들기 본문
여러분은 드래그&드롭을 통해 아이템 간 위치를 바꾸거나 아이템을 스와이프 해 삭제하는 등의 액션을 구현하는 것을 보신 적이 있을 것입니다.
이러한 액션들을 구현하기 위해서는 ItemTouchHelper의 콜백 클래스를 구현하면 됩니다.
Callback 클래스와 SimpleCallback 클래스는 드래그나 스와이프를 인식할 방향을 어디서 설정하느냐의 차이입니다.
class SwipeHelperCallback(private val mAdapter: MyAdapter): ItemTouchHelper.Callback() {
// 입력을 감지할 방향 설정, 설정하지 않으려면 0
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int = makeMovementFlags(UP or DOWN, LEFT)
....
△ 일반 Callback 클래스를 상속받을 경우 getMovementFlags() 함수에서 방향 설정
class SimpleSwipeHelperCallback: ItemTouchHelper.SimpleCallback(UP or DOWN, LEFT or RIGHT) {
....
△ SimpleCallback 클래스를 상속받을 경우 생성자에서 방향 설정
예를 들어 (UP or DOWN, LEFT)를 전달할 경우 드래그 액션과 왼쪽 방향으로의 스와이프만 인식하게 됩니다.
구현
저는 SimpleCallback 클래스를 구현하고 매개변수로 RecyclerView의 어댑터를 넣어 주었습니다.
class SimpleSwipeHelperCallback(private val mAdapter: MyAdapter):
ItemTouchHelper.SimpleCallback(UP or DOWN, LEFT or RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
TODO("Not yet implemented")
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
TODO("Not yet implemented")
}
}
필수적으로 구현해야 하는 함수는 onMove()와 onSwiped() 두 개입니다.
onMove()는 아이템을 드래그할 때, onSwiped()는 아이템을 스와이프 할 때 호출됩니다.
Drag&Drop
먼저 onMove()를 통해 아이템 간 순서 변경을 만들어 보겠습니다.
fun swapData(fromPos: Int, toPos: Int) {
Collections.swap(itemList, fromPos, toPos)
notifyItemMoved(fromPos, toPos)
}
RecyclerView의 어댑터에 두 아이템의 위치를 바꿔주는 swapData()라는 함수를 만들어 주었습니다.
notifyItemMoved() 함수는 ReyclerView.Adapter가 기본 제공하는 함수로 두 위치의 아이템이 바뀌었다는 것을 알립니다.
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
mAdapter.swapData(viewHolder.adapterPosition, target.adapterPosition)
return true
}
그 이후 onMove()에서 두 아이템의 위치와 함께 호출해 주었습니다.
결과
Swipe
스와이프된 항목을 삭제하기 위해, 마찬가지로 RecyclerView의 어댑터에 특정 위치의 아이템을 삭제하는 함수를 만들어 주었습니다. 또, 되돌리기 기능도 만들면 좋겠다 싶어 아이템 추가 함수와 아이템 가져오기 함수도 만들었습니다.
fun insertDataAt(pos: Int, item: String) {
itemList.add(pos, item)
notifyItemInserted(pos)
}
fun dataAt(pos: Int) = itemList[pos]
fun removeDataAt(pos: Int) {
itemList.removeAt(pos)
notifyItemRemoved(pos)
}
삭제는 onSwiped()에서 삭제 함수를 불러주면 끝입니다.
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
mAdapter.removeDataAt(viewHolder.layoutPosition)
}
이제 되돌리기 기능을 만들어 보겠습니다.
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val pos = viewHolder.layoutPosition
val data = mAdapter.dataAt(pos)
mAdapter.removeDataAt(viewHolder.layoutPosition)
Snackbar.make(viewHolder.itemView, "Item Removed.", Snackbar.LENGTH_LONG).setAction("Undo") {
mAdapter.insertDataAt(pos, data)
}.show()
}
삭제할 아이템과 위치를 저장해 두었다가, Undo 버튼을 가진 Snackbar를 띄워 Undo 버튼을 누르면 되돌릴 수 있게 만들었습니다.
참고 링크
'개발 > Android' 카테고리의 다른 글
[Room] Room의 구조와 사용법 (0) | 2022.04.04 |
---|---|
[Android] View에 터치 효과 넣기 (0) | 2022.04.04 |
[TextView] 문자열 리소스를 통해 Html 스타일과 서식을 같이 사용하는 방법 (0) | 2022.03.08 |
[Retrofit] Header Interceptor 추가 (0) | 2022.03.02 |