安卓开发使用 jetpack compose 帮我封装一个拖动LazyColumn的item可改变item位置组件,要求item长按开启拖动,kotlin代码编写完整代码,附上使用方法,
时间: 2023-06-13 13:05:56 浏览: 161
kotdoc-android:使用Jetpack Compose以Kotlin编写的Android应用程序形式的Kotlin语言参考和文档
好的,以下是完整的代码实现:
```kotlin
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.DragHandle
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp
@Composable
fun DragAndDropLazyColumn(
items: List<String>,
onItemMove: (from: Int, to: Int) -> Unit,
onDelete: (index: Int) -> Unit,
modifier: Modifier = Modifier
) {
var draggingIndex by remember { mutableStateOf(-1) }
var dragOffset by remember { mutableStateOf(0f) }
LazyColumn(modifier = modifier) {
items(items.size) { index ->
var isDragging by remember { mutableStateOf(false) }
val painter = rememberVectorPainter(image = Icons.Default.DragHandle)
val deletePainter = rememberVectorPainter(image = Icons.Default.Delete)
Surface(
color = if (isDragging) MaterialTheme.colors.primary.copy(alpha = 0.5f) else MaterialTheme.colors.surface,
elevation = if (isDragging) 8.dp else 2.dp,
modifier = Modifier
.height(64.dp)
.fillMaxWidth()
.padding(8.dp)
.pointerInput(Unit) {
detectDragGestures(
onDragStart = {
isDragging = true
draggingIndex = index
dragOffset = 0f
},
onDragEnd = {
isDragging = false
if (dragOffset != 0f) {
val from = draggingIndex
val to = if (dragOffset > 0) index - 1 else index
onItemMove(from, to)
}
draggingIndex = -1
dragOffset = 0f
},
onDrag = { change, dragAmount ->
dragOffset = dragAmount.y
change.consumeAllChanges()
}
)
}
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxSize()
) {
Icon(
painter = painter,
contentDescription = "Drag Handle",
modifier = Modifier.padding(start = 16.dp, end = 16.dp)
)
Text(
text = items[index],
modifier = Modifier.weight(1f)
)
IconButton(
onClick = { onDelete(index) },
content = { Icon(painter = deletePainter, contentDescription = "Delete") },
modifier = Modifier.padding(end = 16.dp)
)
}
}
}
}
}
```
在这个组件中,我们通过 `LazyColumn` 来展示数据列表,并使用 `Surface` 组件包裹每个列表项。我们使用 `pointerInput` 监听拖动手势,当手势开始时,我们将 `isDragging` 置为 `true` 并保存当前拖动的项的索引和拖动偏移量。当手势结束时,我们将 `isDragging` 置为 `false`,如果拖动了项,我们将调用 `onItemMove` 回调函数将其移动到新的位置,否则不做任何操作。在拖动过程中,我们更新 `dragOffset` 的值,以便稍后计算新位置。
要使用这个组件,只需将其添加到您的界面中,然后将数据列表、`onItemMove` 和 `onDelete` 回调函数传递给它即可:
```kotlin
val items = List(20) { "Item $it" }
DragAndDropLazyColumn(
items = items,
onItemMove = { from, to ->
items.move(from, to)
},
onDelete = { index ->
items.removeAt(index)
},
modifier = Modifier.fillMaxSize()
)
```
在这个示例中,我们创建了一个包含 20 个项的列表,并将其传递给 `DragAndDropLazyColumn`。我们还定义了两个回调函数:`onItemMove` 用于在拖动项时移动它们,`onDelete` 用于删除项。最后,我们将 `DragAndDropLazyColumn` 放入 `Box` 中,并使用 `Modifier.fillMaxSize()` 将其填充到整个屏幕。
阅读全文