このサンプルは、Recycler view を使ったリストビューで
1行をつかんで縦方向にドラッグすることで順番を変えることができます。
スイッチオンの時にドラッグができるようになっています。
行をつかむと、その行が薄くなるようにalphaを変更しています。
リストビューの作り方については過去の記事をご参照ください。
data class MyData(
var name: String
)
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.sampledraglistitem.databinding.ListItemBinding
class MyAdapter(private val myList: MutableList<MyData>) : RecyclerView.Adapter<MyAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val binding = ListItemBinding.bind(view)
val txvName = binding.txvSample
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.txvName.text = myList[position].name
}
override fun getItemCount(): Int {
return myList.size
}
}
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
class MyItemTouchHelper {
companion object {
fun getCallback(mutableList: MutableList<*>) =
object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN, 0)
{
// For up and down dragging.
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val fromPosition = viewHolder.adapterPosition
val toPosition = target.adapterPosition
@Suppress("UNCHECKED_CAST")
val list = mutableList as MutableList<Any>
val tempData = list[fromPosition]
list.removeAt(fromPosition)
list.add(toPosition, tempData)
recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
return true
}
// For swiping left and right. Not used in this case. (swipeDirs = 0)
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
}
// Selected row is highlighted.
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
when (actionState) {
ItemTouchHelper.ACTION_STATE_DRAG -> {
viewHolder?.itemView?.alpha = 0.6f
}
}
}
// The row is not highlighted when unselected.
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.alpha = 1.0f
}
}
}
}
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.sampledraglistitem.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Create my list.
val myList = mutableListOf<MyData>()
for (i in 1..10) {
myList.add(MyData("item$i"))
}
// Setting for recycler view.
val adapter = MyAdapter(myList)
binding.rcvSample.layoutManager = LinearLayoutManager(this)
binding.rcvSample.adapter = adapter
// Activate Item touch helper.
val helper = ItemTouchHelper(MyItemTouchHelper.getCallback(myList))
binding.swtCanSort.setOnCheckedChangeListener { buttonView, isChecked ->
if (isChecked) {
helper.attachToRecyclerView(binding.rcvSample)
} else {
helper.attachToRecyclerView(null)
}
}
}
}
<?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/rcvSample"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/swtCanSort" />
<Switch
android:id="@+id/swtCanSort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="Sortable"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?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="wrap_content"
android:layout_marginTop="2dp"
android:background="#272727">
<TextView
android:id="@+id/txvSample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>