Как исправить ошибку перетаскивания задач перетаскивания в составлении реактивного ранца?Android

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Как исправить ошибку перетаскивания задач перетаскивания в составлении реактивного ранца?

Сообщение Anonymous »

Я пытаюсь написать ответ на этот вопрос, но при тестировании своего кода обнаружил ошибку, которую не могу понять, как исправить.
Приложение диспетчер задач, в котором вы можете перетаскивать задачи между очередями: «Сделать», «В процессе» и «Готово». В каждой очереди есть список задач, и перетаскивание задачи перемещает ее из одной очереди в другую.
Вот минимальный пример моего кода для воспроизведения проблемы:

Код: Выделить всё

implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5")

Код: Выделить всё

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
App(modifier = Modifier
.padding(innerPadding)
)
}
}
}
}

enum class QueueType(val title: String) {
TodoQueue("To Do"),
InProgressQueue("In Progress"),
DoneQueue("Done")
}

data class Task(
val title: String,
val description: String
)

class MyViewModel: ViewModel() {

val todoTasks = mutableStateListOf(
Task("Task 1", "Description 1"),
Task("Task 4", "Description 4"),
)

val inProgressTasks = mutableStateListOf(
Task("Task 2", "Description 2"),
Task("Task 5", "Description 5"),
)

val doneTasks = mutableStateListOf(
Task("Task 3", "Description 3"),
)

fun moveTask(
task: Task,
from: QueueType,
to: QueueType
) {
when(from) {
QueueType.TodoQueue -> todoTasks.remove(task)
QueueType.InProgressQueue -> inProgressTasks.remove(task)
QueueType.DoneQueue -> doneTasks.remove(task)
}
when(to) {
QueueType.TodoQueue -> todoTasks.add(task)
QueueType.InProgressQueue -> inProgressTasks.add(task)
QueueType.DoneQueue -> doneTasks.add(task)
}
}
}

data class DraggedData(
val task: Task,
val originQueue: QueueType,
)

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun TaskCard(
task: Task,
queueType: QueueType,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
.dragAndDropSource {
detectTapGestures(
onLongPress = {
startTransfer(
DragAndDropTransferData(
ClipData.newPlainText("Task", "Task"),

passe data to be used later when dropping the card
localState = DraggedData(task, queueType)
)
)
}
)
}
.background(
color = Color.LightGray,
shape = RoundedCornerShape(8.dp)
)
.padding(vertical = 4.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(text = task.title)
Text(text = task.description)
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun QueueTask(
queueType: QueueType,
tasks: List,
modifier: Modifier = Modifier,
onTaskDrop: (Task, QueueType) ->  Unit
) {
val dropTarget = remember {
object : DragAndDropTarget {
override fun onDrop(dragStartEvent: DragAndDropEvent): Boolean {
val dropEvent = dragStartEvent.toAndroidDragEvent()

// get the dragged data from localState passed earlier
val draggedTaskData = dropEvent.localState as? DraggedData
val droppedTask = draggedTaskData?.task
droppedTask?.let { onTaskDrop(it, draggedTaskData.originQueue) }
return true
}
}
}

Column(
modifier = modifier
.dragAndDropTarget (
shouldStartDragAndDrop = { dragStartEvent ->
dragStartEvent.mimeTypes().contains(ClipDescription.MIMETYPE_TEXT_PLAIN)
}, target = dropTarget
)
.border(
width = 1.dp,
color = Color.Black,
shape = RoundedCornerShape(8.dp)
)
.fillMaxHeight(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = queueType.title)
Spacer(modifier = Modifier.height(4.dp))
tasks.forEach { task ->
TaskCard(
task = task,
queueType = queueType,
modifier = Modifier
.padding(vertical = 4.dp)
)
}
}
}

@Composable
fun App(
modifier: Modifier = Modifier,
viewModel: MyViewModel = viewModel()
) {

val todoTasks = viewModel.todoTasks
val inProgressTasks = viewModel.inProgressTasks
val doneTasks = viewModel.doneTasks

Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(10.dp)
) {
QueueTask(
queueType = QueueType.TodoQueue,
tasks = todoTasks,
modifier = Modifier.weight(1f),
onTaskDrop = { task, fromQueueType ->
viewModel.moveTask(task, fromQueueType, QueueType.TodoQueue)
}
)
QueueTask(
queueType = QueueType.InProgressQueue,
tasks = inProgressTasks,
modifier = Modifier.weight(1f),
onTaskDrop = { task, fromQueueType ->
viewModel.moveTask(task, fromQueueType, QueueType.InProgressQueue)
}
)
QueueTask(
queueType = QueueType.DoneQueue,
tasks = doneTasks,
modifier = Modifier.weight(1f),
onTaskDrop = { task, fromQueueType ->
viewModel.moveTask(task, fromQueueType, QueueType.DoneQueue)
}
)
}
}
Код в основном работает, но в некоторых сценариях происходит неожиданное поведение:
Сценарий 1:
  • Переместить задачу 2 из «Выполняется» в «Сделать» --> Работает нормально.
    < li>Переместить задачу 1 из списка дел в список задач --> Работает нормально.
  • Переместить задачу 4 из списка задач в «Выполняется» --> ОШИБКА: «Задача 1» дублируется, а задача 4 не перемещается.
Изображение

Сценарий 2:
  • Переместить задачу 1 из задачи в задачу (та же очередь) --> работает нормально.
    Переместить задачу 4 из списка дел в список дел (та же очередь) --> ОШИБКА: ничего не происходит.
Изображение
При отладке я заметил, что иногда в лямбду onTaskDrop передается неправильная задача. Например, даже если я перетаскиваю задачу 1, обрабатывается другая задача.
Похоже, что localState, переданный в процессе перетаскивания, может не всегда соответствовать перетаскиваемой задаче.
Похоже, проблема связана с порядком задач в очереди!
Что может быть причиной этих проблем и как их устранить?>

Подробнее здесь: https://stackoverflow.com/questions/792 ... ck-compose
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»