728x90
반응형
RecyclerView 에서 순서 정렬을 할 때 많이 쓰이는 Drag & Drop 기능에 대해서 간단하게 포스팅 하겠습니다.
- 저는 예제에 Databinding 을 사용했습니다.
// build.gradle (:app)
android {
buildFeatures {
dataBinding true
}
}
activity_main.xml
- RecyclerView 하나 있는 예제 화면입니다.
<?xml version="1.0" encoding="utf-8"?>
<layout
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"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
item_profile.xml
- RecyclerView 에 들어갈 UI 입니다.
- ImageView 에 들어갈 파일은 Vector Asset 으로 추가합니다.
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="5dp"
app:cardCornerRadius="26dp"
android:layout_margin="8dp"
>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="10dp"
android:paddingHorizontal="20dp">
<ImageView
android:id="@+id/ivProfile"
android:layout_width="80dp"
android:layout_height="80dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/ic_profile"
/>
<TextView
android:id="@+id/tvName"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/ivProfile"
app:layout_constraintEnd_toStartOf="@id/ivHamburger"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginHorizontal="20dp"
android:textSize="20dp"
android:textColor="@color/black"
tools:text="닉네임"
/>
<ImageView
android:id="@+id/ivHamburger"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@+id/tvName"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:src="@drawable/ic_hamburger"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</layout>
ProfileAdapter.kt
- RecyclerView 에 사용될 어댑터 입니다.
- moveItem() 와 startDrag 로 Drag & Drop 을 동작합니다.
- LongPress 로만 Drag & Drop 을 사용하시려면 startDrag 는 필요없습니다.
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.dragdrop.databinding.ItemProfileBinding
import java.util.*
class ProfileAdapter(
private val startDrag : (holder : RecyclerView.ViewHolder) -> Unit
) : RecyclerView.Adapter<ProfileAdapter.ViewHolder>() {
private val items = mutableListOf<String>()
fun setItems(profiles : List<String>) {
items.addAll(profiles)
}
fun moveItem(from: Int, to: Int) {
Collections.swap(items, from, to)
notifyItemMoved(from, to)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflatedView = LayoutInflater.from(parent.context)
val binding = ItemProfileBinding.inflate(inflatedView, parent, false)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = items[position]
holder.bind(item)
}
override fun getItemCount() = items.count()
inner class ViewHolder(
private val binding: ItemProfileBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item : String) {
binding.apply {
tvName.text = item
ivHamburger.setOnTouchListener { _, _ ->
startDrag(this@ViewHolder)
false
}
}
}
}
}
MainActivity.kt
- Drag & Drop 을 사용하기 위해 itemTouchHelper 를 구현합니다.
- 햄버거 버튼을 누르면 onSelectedChanged 가 호출되고 위 아래로 움직일 때 onMove 가 호출됩니다.
- onMove 에서 구현했던 아이템 변경 처리를 해주고 아이템을 놓는다면 onClearView 가 호출됩니다.
- 이렇게 구현한 itemTouchHelper 를 attachToRecyclerView 를 통해 RecyclerView 에 연결해주면 구현이 끝납니다.
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import com.example.dragdrop.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var profileAdapter: ProfileAdapter
private val profiles = listOf(
"프로필_1",
"프로필_2",
"프로필_3",
"프로필_4",
"프로필_5",
)
private val itemTouchHelper by lazy {
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.START or ItemTouchHelper.END,
0
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val adapter = recyclerView.adapter as ProfileAdapter
val from = viewHolder.adapterPosition
val to = target.adapterPosition
adapter.moveItem(from, to)
return true
}
override fun isLongPressDragEnabled() = false
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
viewHolder?.itemView?.alpha = 0.5f
}
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.alpha = 1.0f
}
}
ItemTouchHelper(simpleItemTouchCallback)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
initView()
}
private fun initView() {
binding.apply {
profileAdapter = ProfileAdapter {
itemTouchHelper.startDrag(it)
}
itemTouchHelper.attachToRecyclerView(recyclerView)
recyclerView.adapter = profileAdapter
profileAdapter.setItems(profiles)
}
}
}
728x90
반응형
'Android > UI' 카테고리의 다른 글
[Android] BottomSheetDialog 만들기 (0) | 2019.11.05 |
---|