Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Kotlin
- RecyclerView
- javascript
- retrofit2
- CSS
- CalendarView
- dispatchQueue
- viewpager2
- MemoList
- ViewModel
- UIPickerView
- web
- imagepicker
- ayncAfter
- RxJava
- Alamofire
- HTML
- 실행지연
- MotionEvent
- 개발
- DispatchTouchEvent
- progressbar
- aab
- SWIFT
- InAppPurchase
- SplashFragment
- Dropdown
- 스터디
- Android
- IOS
Archives
- Today
- Total
멜팅비의 개발 공부
[Android/Kotlin] RecyclerView Drag&Drop, Swipe 구현하기 본문
반응형
RecyclerView의 Item 순서를 변경 - Drag & Drop, RecyclerView의 Item을 밀어서 삭제하기 - Swipe
기능을 라이브러리를 사용하지 않고 ItemTouchHelper를 통해 구현하는 방법을 정리하려고 한다.
먼저, RecyclerView를 구현하기 위해 XML을 작성한다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
item_linear.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="50dp">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textColor="@color/black"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/imageView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginEnd="20dp"
android:background="@drawable/ic_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
ItemTouchHelper는 Android Support Lib에서 제공해주기 때문에 쉽게 구현이 가능하다.
ItemTouchHelper를 사용하기 위해서는 ItemTouchHelpder.Callback을 구현해야 한다.
ItemTouchHelperCallback.kt
class ItemTouchHelperCallback(
private val itemMoveListener: OnItemMoveListener
) : ItemTouchHelper.Callback() {
interface OnItemMoveListener {
fun onItemMoved(fromPosition: Int, toPosition: Int)
fun onItemSwiped(position: Int)
}
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
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
itemMoveListener.onItemSwiped(viewHolder.adapterPosition)
}
override fun isLongPressDragEnabled(): Boolean = false
}
getMovementFlags() : 이벤트의 방향을 설정, 어느 방향으로 움직 일지에 따라 flag를 정의
onMove() : 어느 위치에서 어느 위치로 변경하는지 이벤트를 받음
onSwiped(): Swipe가 될 때 이벤트
RecyclerViewAdapter에서 ItemTouchHelperAdapter를 구현한다.
LinearListViewAdapter.kt
class LinearListViewAdapter(private val list: MutableList<String>) :
RecyclerView.Adapter<LinearListViewAdapter.ViewHolder>(),
ItemTouchHelperCallback.OnItemMoveListener {
private lateinit var dragListener: OnStartDragListener
inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_linear, parent, false)
) {
val tvTitle: TextView = itemView.findViewById(R.id.tv_title)
val ivMenu: ImageView = itemView.findViewById(R.id.imageView)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(parent)
}
@SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
list[position].let {
with(holder) {
tvTitle.text = it
ivMenu.setOnTouchListener { view, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
dragListener.onStartDrag(this)
}
return@setOnTouchListener false
}
}
}
}
override fun getItemCount(): Int {
return list.size
}
interface OnStartDragListener {
fun onStartDrag(viewHolder: RecyclerView.ViewHolder)
}
fun startDrag(listener: OnStartDragListener) {
this.dragListener = listener
}
override fun onItemMoved(fromPosition: Int, toPosition: Int) {
Collections.swap(list, fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
}
override fun onItemSwiped(position: Int) {
list.removeAt(position)
notifyItemRemoved(position)
}
}
MainActivity에서 adapter와 ItemTouchHelperCallback을 연결한다.
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
val list = mutableListOf("category1", "category2", "category3", "category4", "category5")
val adapter = LinearListViewAdapter(list)
recyclerView.layoutManager = LinearLayoutManager(this)
val callback = ItemTouchHelperCallback(adapter)
val touchHelper = ItemTouchHelper(callback)
touchHelper.attachToRecyclerView(recyclerView)
recyclerView.adapter = adapter
adapter.startDrag(object : LinearListViewAdapter.OnStartDragListener {
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
touchHelper.startDrag(viewHolder)
}
})
}
}
다음편으로 GridLayout에서 ItemTouchHelperCallback을 사용했을 때를 정리할 예정이다.
반응형
'개발 공부 > [Android 개발]' 카테고리의 다른 글
[Android/Kotlin] dispatchTouchEvent 사용하기 - 터치 이벤트 감지 (0) | 2021.10.07 |
---|---|
[Android/Kotlin] RecyclerView Drag&Drop 구현하기2 - GridLayout (0) | 2021.10.07 |
[Android/Kotlin] 안드로이드 인앱 결제(구독상품) 구현 정리 (3) | 2021.09.15 |
[Android/Kotlin] 유용한 Custom Calendar Library 소개 (0) | 2021.09.09 |
[Android/Kotlin] retrofit2 사용 시 Response가 XML인 경우 Convert 하는 방법 (0) | 2021.09.09 |
Comments