refactor(ui): Vereinheitlichung des Drag-and-Drop-Verhaltens
Das Drag-and-Drop-Verhalten für Einkaufslisten und deren Einträge wurde überarbeitet und vereinheitlicht, um eine konsistentere und intuitivere Benutzererfahrung zu schaffen. - Das separate Verschiebe-Icon wurde sowohl in der Listen- als auch in der Detailansicht entfernt. Stattdessen kann nun das gesamte Element (Karte oder Zeile) durch langes Drücken verschoben werden. - In der Detailansicht werden die Artikel nun als 'Cards' dargestellt, um beim Verschieben ein klares visuelles Feedback (Schatten/Anhebung) zu geben, analog zur Listenansicht. - Das Bearbeiten-Icon in der Detailansicht wurde durch ein "Mehr"-Menü ersetzt. Dieses Menü bietet nun die Optionen "Umbenennen" und "Menge ändern" und sorgt für eine klare und explizite Interaktion.
This commit is contained in:
@@ -15,9 +15,14 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.rounded.DragHandle
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -147,38 +152,60 @@ fun ShoppingListDetailScreen(
|
||||
) {
|
||||
items(filteredItems, { it.id }) { item ->
|
||||
ReorderableItem(reorderableLazyListState, key = item.id) { isDragging ->
|
||||
val elevation = animateDpAsState(if (isDragging) 0.dp else 0.dp, label = "elevation")
|
||||
val elevation = animateDpAsState(if (isDragging) 4.dp else 0.dp, label = "elevation")
|
||||
val scale = animateFloatAsState(if (isDragging) 1.05f else 1.0f, label = "scale")
|
||||
val isSelected = item == selectedItem
|
||||
val backgroundColor = animateColorAsState(
|
||||
if (isDragging) MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.7f)
|
||||
else if (isSelected) MaterialTheme.colorScheme.surfaceVariant
|
||||
else Color.Transparent, label = "backgroundColor"
|
||||
)
|
||||
Row(
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp)
|
||||
.draggableHandle()
|
||||
.graphicsLayer {
|
||||
scaleX = scale.value
|
||||
scaleY = scale.value
|
||||
}
|
||||
.shadow(elevation.value)
|
||||
.background(backgroundColor.value)
|
||||
.clickable(interactionSource = remember { MutableInteractionSource() }, indication = null) { coroutineScope.launch {
|
||||
viewModel.saveShoppingListItem(item.copy(isChecked = !item.isChecked))
|
||||
.shadow(elevation.value),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { // The check/uncheck logic
|
||||
coroutineScope.launch {
|
||||
viewModel.saveShoppingListItem(item.copy(isChecked = !item.isChecked))
|
||||
}
|
||||
}
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = if (item.quantity != null) "${item.name} (${item.quantity})" else item.name,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textDecoration = if (item.isChecked) TextDecoration.LineThrough else null,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
var showMenu by remember { mutableStateOf(false) }
|
||||
IconButton(onClick = {
|
||||
viewModel.onSelectItem(item)
|
||||
showMenu = true
|
||||
}) {
|
||||
Icon(Icons.Default.MoreVert, contentDescription = "More options")
|
||||
DropdownMenu(expanded = showMenu, onDismissRequest = { showMenu = false }) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.rename_item_title)) },
|
||||
onClick = {
|
||||
viewModel.onShowRenameDialog(true)
|
||||
showMenu = false
|
||||
}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.change_quantity)) },
|
||||
onClick = {
|
||||
viewModel.onShowQuantityDialog(true)
|
||||
showMenu = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
.padding(vertical = 8.dp, horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = if (item.quantity != null) "${item.name} (${item.quantity})" else item.name,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textDecoration = if (item.isChecked) TextDecoration.LineThrough else null,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
IconButton(modifier = Modifier.draggableHandle(onDragStarted = { viewModel.onSelectItem(item) }), onClick = { }) {
|
||||
Icon(Icons.Rounded.DragHandle, contentDescription = "Reorder")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ fun ShoppingListCard(
|
||||
else Color.Transparent, label = "backgroundColor"
|
||||
)
|
||||
Card(
|
||||
modifier = modifier
|
||||
modifier = with(scope) { modifier.draggableHandle() }
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp, horizontal = 16.dp)
|
||||
.graphicsLayer {
|
||||
@@ -202,9 +202,6 @@ fun ShoppingListCard(
|
||||
IconButton(onClick = { onDeleteList(listWithItems) }) {
|
||||
Icon(Icons.Default.Delete, contentDescription = stringResource(R.string.delete_list))
|
||||
}
|
||||
IconButton(modifier = with(scope) { Modifier.draggableHandle() }, onClick = { }) {
|
||||
Icon(Icons.Rounded.DragHandle, contentDescription = "Reorder")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user