그리드레이아웃을 가진 리사이클러뷰 드래그앤드롭을 구현하였는데, 까먹기 전에 정리하려고 한다.
필요한 준비물은 MyTouchHelperCallback 코틀린파일과 DragAndDropAdapter 구현해야한다.
(당연히 RecyclerView는 다 구현이 되어있어야겠죠?)
MyTouchHelperCallback.kt
ItemTouchHelper를 사용하기 위해서 ItemTouchHelper.CallBack을 구현해야한다.
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
class MyTouchHelperCallback(
private val itemMoveListener: OnItemMoveListener
) : ItemTouchHelper.Callback() {
interface OnItemMoveListener {
fun onItemMove(fromPosition: Int, toPosition: Int)
fun onItemSwiped(position: Int)
}
/**
* 어느 방향으로 움직일지에 따라서 flag 받는것을 정의
* 드래그는 위, 아래 액션이기 때문에 up, down 을 넘겨줌
*/
override fun getMovementFlags(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
): Int {
// GridLayout 형식일 경우
val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
val swipeFlags = 0
return makeMovementFlags(dragFlags, swipeFlags)
}
/**
* 어느 위치에서 어느 위치로 변경하는지
*/
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
itemMoveListener.onItemMove(viewHolder.adapterPosition, target.adapterPosition)
return true
}
/**
* 좌우 스와이프
*/
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
itemMoveListener.onItemSwiped(viewHolder.adapterPosition)
}
// 길게 눌렀을 때 반응하는 함수
override fun isLongPressDragEnabled(): Boolean = false
}
DragAndDropAdapter.kt
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.rc_4.R
import com.example.rc_4.ZZimData
import com.example.rc_4.databinding.RvZzimPageItemBinding
import java.util.*
import kotlin.collections.ArrayList
class DragAndDropAdapter(private val list: ArrayList<ZZimData>) :
RecyclerView.Adapter<DragAndDropAdapter.ViewHolder>(),
MyTouchHelperCallback.OnItemMoveListener {
private lateinit var dragListener: OnStartDragListener
lateinit var binding: RvZzimPageItemBinding
inner class ViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.rv_zzim_page_item, parent, false)
) {
val mall_name: TextView = itemView.findViewById(R.id.tv_mall_name)
val product_name: TextView = itemView.findViewById(R.id.tv_product_name)
val sale: TextView = itemView.findViewById(R.id.tv_sale)
val price: TextView = itemView.findViewById(R.id.tv_price)
val ivMenu: ImageView = itemView.findViewById(R.id.iv_proudct_img)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
binding = RvZzimPageItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(parent)
}
// inner class ViewHolder(val binding: RvZzimPageItemBinding) : RecyclerView.ViewHolder(binding.root)
// }
@SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
list[position].let {
with(holder) {
mall_name.text = it.mall_name
product_name.text = it.product_name
price.text = it.price
sale.text=it.sale
ivMenu.setImageResource(it.img)
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
}
fun onItemMoved(fromPosition: Int, toPosition: Int) {
Collections.swap(list, fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
}
override fun onItemMove(fromPosition: Int, toPosition: Int) {
Collections.swap(list, fromPosition, toPosition)
notifyItemMoved(fromPosition, toPosition)
}
override fun onItemSwiped(position: Int) {
list.removeAt(position)
notifyItemRemoved(position)
}
}
MainActivity.kt
만든 어댑터를 메인액티비티에 붙여주면 끝!
val adapter = DragAndDropAdapter(dataList)
val callback = MyTouchHelperCallback(adapter)
val touchHelper = ItemTouchHelper(callback)
touchHelper.attachToRecyclerView(binding.rvZzimPage)
binding.rvZzimPage.adapter = adapter
adapter.startDrag(object : DragAndDropAdapter.OnStartDragListener {
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
touchHelper.startDrag(viewHolder)
}
})
결과물
'개발 > Android' 카테고리의 다른 글
[안드로이드] No type arguments expected for class Call 에러 (0) | 2022.03.15 |
---|---|
[안드로이드] Recyclerview footer 사용 (0) | 2022.03.15 |
[안드로이드] TabLayout + Fragment 사용하기 (0) | 2022.02.27 |
[안드로이드] 스크롤 시 체크박스 해제되는 문제 해결 (0) | 2022.02.27 |
[안드로이드] RecyclerView 사용하기 ( + ViewBinding, Fragment) (0) | 2022.02.27 |