安卓开发 jetpack compose 帮我封装一个拖动LazyColumn的item可改变item位置组件,item长按开启拖动 要求使用 material3 ,kotlin代码编写完整代码,附上使用方法
时间: 2023-06-13 20:06:06 浏览: 285
谷歌最新技术,Android开发,Jetpack Compose,Jetpack架构组件
好的,我来为你封装一个拖动 LazyColumn 的 item 可改变位置的组件。
首先,我们需要使用 `LazyColumn` 和 `Box` 来实现列表和拖动效果。然后,我们需要监听 `Box` 的 `onTouch` 事件来实现拖动效果。最后,我们需要在拖动结束后更新数据源,并刷新列表。
下面是完整代码:
```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.consumePositionChange
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
@ExperimentalMaterial3Api
@Composable
fun DragSortLazyColumn(
modifier: Modifier = Modifier,
items: List<String>,
onItemsChanged: (List<String>) -> Unit
) {
var draggingIndex by remember { mutableStateOf(-1) }
var dragOffset by remember { mutableStateOf(Offset.Zero) }
var lastDragPosition by remember { mutableStateOf(Offset.Zero) }
var dragDirection by remember { mutableStateOf(0) }
LazyColumn(modifier = modifier) {
itemsIndexed(items) { index, item ->
Column {
if (draggingIndex == index) {
Surface(
modifier = Modifier.height(LocalDensity.current.run { 60.dp.toPx() }),
color = MaterialTheme.colors.onSurface.copy(alpha = 0.1f)
) {
Box(
Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 0.5f))
)
Box(
Modifier
.fillMaxSize()
.background(MaterialTheme.colors.surface)
) {
MaterialTheme.typography.body1.toFontFamily().font(
weight = LocalTextStyle.current.fontWeight,
fontSize = LocalTextStyle.current.fontSize,
).draw(
text = item,
color = LocalContentColor.current,
maxWidth = LocalDensity.current.run { 300.dp.toPx() },
overflow = TextOverflow.Ellipsis,
canvas = drawScope
)
}
}
} else {
Surface(
modifier = Modifier.height(LocalDensity.current.run { 60.dp.toPx() }),
color = MaterialTheme.colors.surface
) {
Box(
Modifier
.fillMaxSize()
.background(MaterialTheme.colors.surface)
.pointerInput(Unit) {
detectTapGestures(
onTap = {
draggingIndex = index
dragOffset = Offset.Zero
lastDragPosition = Offset.Zero
dragDirection = 0
}
)
detectDragGestures(
onDragStart = {
draggingIndex = index
dragOffset = it
lastDragPosition = it
dragDirection = 0
it.consumePositionChange()
},
onDrag = { change, dragAmount ->
dragOffset += dragAmount
val currentPosition = change.position
dragDirection = currentPosition.y
.compareTo(lastDragPosition.y)
lastDragPosition = currentPosition
it.consumePositionChange()
},
onDragEnd = {
if (draggingIndex != -1) {
val newIndex = if (dragDirection < 0) {
index - 1
} else {
index + 1
}
if (newIndex in items.indices) {
val newItems = items.toMutableList()
newItems.removeAt(draggingIndex)
newItems.add(newIndex, item)
onItemsChanged(newItems)
}
draggingIndex = -1
}
}
)
}
) {
MaterialTheme.typography.body1.toFontFamily().font(
weight = LocalTextStyle.current.fontWeight,
fontSize = LocalTextStyle.current.fontSize,
).draw(
text = item,
color = LocalContentColor.current,
maxWidth = LocalDensity.current.run { 300.dp.toPx() },
overflow = TextOverflow.Ellipsis,
canvas = drawScope
)
}
}
}
}
}
}
}
```
使用方法:
```kotlin
val items = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")
var newItems by remember { mutableStateOf(items) }
DragSortLazyColumn(
items = newItems,
onItemsChanged = { newItems = it }
)
```
这样就完成了一个拖动 LazyColumn 的 item 可改变位置的组件。
阅读全文