feat: enhance ListDetailScreen layout with auto-scrolling and resizing improvements

This commit is contained in:
2025-10-29 10:09:30 +01:00
parent bf982deb9a
commit 7761ccdf03
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
@@ -56,6 +57,7 @@ import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -87,6 +89,7 @@ import org.burnoutcrew.reorderable.reorderable
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Locale import java.util.Locale
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable @Composable
@@ -402,9 +405,11 @@ fun ListDetailScreen(
width = fieldWidths[field.id] ?: 150.dp, width = fieldWidths[field.id] ?: 150.dp,
onWidthChange = { delta -> onWidthChange = { delta ->
val currentWidth = fieldWidths[field.id] ?: 150.dp val currentWidth = fieldWidths[field.id] ?: 150.dp
val newWidth = (currentWidth.value + delta).coerceIn(100f, 400f) // Enforce only a minimum width; remove the previous max (400dp)
val newWidth = (currentWidth.value + delta).coerceAtLeast(100f)
fieldWidths[field.id] = newWidth.dp fieldWidths[field.id] = newWidth.dp
}, },
scrollState = horizontalScrollState,
) )
} }
} }
@@ -596,8 +601,10 @@ fun FieldHeader(
field: Field, field: Field,
width: Dp, width: Dp,
onWidthChange: (Float) -> Unit, onWidthChange: (Float) -> Unit,
scrollState: androidx.compose.foundation.ScrollState,
) { ) {
val density = LocalDensity.current val density = LocalDensity.current
val scope = rememberCoroutineScope()
Box( Box(
modifier = modifier =
@@ -634,6 +641,15 @@ fun FieldHeader(
with(density) { with(density) {
onWidthChange(dragAmount.x.toDp().value) onWidthChange(dragAmount.x.toDp().value)
} }
// Auto-scroll when resizing near the edges to keep the handle visible
val edgePx = with(density) { 32.dp.toPx() }
if (dragAmount.x > 0 && scrollState.value.toFloat() >= (scrollState.maxValue - edgePx)) {
val target = (scrollState.value.toFloat() + edgePx / 2f).coerceAtMost(scrollState.maxValue.toFloat())
scope.launch { scrollState.scrollTo(target.toInt()) }
} else if (dragAmount.x < 0 && scrollState.value.toFloat() <= edgePx) {
val target = (scrollState.value.toFloat() - edgePx / 2f).coerceAtLeast(0f)
scope.launch { scrollState.scrollTo(target.toInt()) }
}
} }
}, },
) { ) {
@@ -670,6 +686,7 @@ fun ItemRow(
modifier = modifier =
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.height(IntrinsicSize.Min)
.clickable(onClick = onClick) .clickable(onClick = onClick)
.horizontalScroll(scrollState), .horizontalScroll(scrollState),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@@ -683,6 +700,7 @@ fun ItemRow(
modifier = modifier =
Modifier Modifier
.width(fieldWidth) .width(fieldWidth)
.fillMaxHeight()
.border( .border(
width = 1.dp, width = 1.dp,
color = MaterialTheme.colorScheme.outline, color = MaterialTheme.colorScheme.outline,