android: scroll the subboard grid vertically

5662d6d · gmorell · 2026-06-25 15:36

11 files +43 -14
Message
{commit_body(@commit)}

Files changed

modified android/app/src/main/java/org/neiam/waxx/app/ui/BoardScreen.kt
+43 −14
@@ -19,6 +19,7 @@ import androidx.compose.foundation.lazy.LazyColumn
19 19 import androidx.compose.foundation.lazy.items
20 20 import androidx.compose.foundation.rememberScrollState
21 21 import androidx.compose.foundation.shape.RoundedCornerShape
22 +import androidx.compose.foundation.verticalScroll
22 23 import androidx.compose.ui.input.pointer.pointerInput
23 24 import androidx.compose.ui.layout.ContentScale
24 25 import androidx.compose.ui.layout.onGloballyPositioned
@@ -353,6 +354,9 @@ private fun Kanban(
353 354 }
354 355
355 356 val scrollState = rememberScrollState()
357 + // Vertical scroll for the 2-D (subboard) grid so rows past the viewport
358 + // aren't clipped. Unused in the 1-D layout (columns scroll themselves).
359 + val verticalScrollState = rememberScrollState()
356 360 var viewportBounds by remember { mutableStateOf<Rect?>(null) }
357 361 val density = LocalDensity.current
358 362 val edgePx = with(density) { 80.dp.toPx() }
@@ -414,6 +418,7 @@ private fun Kanban(
414 418 modifier = modifier
415 419 .onGloballyPositioned { viewportBounds = it.boundsInWindowSafe() }
416 420 .horizontalScroll(scrollState)
421 + .verticalScroll(verticalScrollState)
417 422 .padding(horizontal = 8.dp, vertical = 8.dp),
418 423 verticalArrangement = Arrangement.spacedBy(8.dp),
419 424 ) {
@@ -465,6 +470,7 @@ private fun Kanban(
465 470 onOpenCard = onOpenCard,
466 471 onDropFinished = onDropFinished,
467 472 cellWidth = 240.dp,
473 + cardsScrollable = false,
468 474 )
469 475 }
470 476 }
@@ -485,6 +491,10 @@ private fun StageCell(
485 491 onOpenCard: (CardSummary) -> Unit,
486 492 onDropFinished: () -> Unit,
487 493 cellWidth: androidx.compose.ui.unit.Dp = 280.dp,
494 + // When the whole grid scrolls (2-D subboard layout), cells lay their cards
495 + // out non-lazily so we don't nest a vertical scroll inside a vertical
496 + // scroll. In the 1-D layout each column scrolls itself, so this stays true.
497 + cardsScrollable: Boolean = true,
488 498 ) {
489 499 val session = dragState.session
490 500 val isSource = session != null &&
@@ -553,20 +563,39 @@ private fun StageCell(
553 563 )
554 564 }
555 565 } else {
556 − LazyColumn(
557 − verticalArrangement = Arrangement.spacedBy(4.dp),
558 − contentPadding = PaddingValues(vertical = 2.dp),
559 − ) {
560 − items(cards.sortedBy { it.position }, key = { it.id }) { c ->
561 − CardChip(
562 − card = c,
563 − fromStageId = stage.id,
564 − fromSubboardId = subboard?.id,
565 − creds = creds,
566 − dragState = dragState,
567 − onClick = { onOpenCard(c) },
568 − onDropFinished = onDropFinished,
569 − )
566 + val sorted = cards.sortedBy { it.position }
567 + if (cardsScrollable) {
568 + LazyColumn(
569 + verticalArrangement = Arrangement.spacedBy(4.dp),
570 + contentPadding = PaddingValues(vertical = 2.dp),
571 + ) {
572 + items(sorted, key = { it.id }) { c ->
573 + CardChip(
574 + card = c,
575 + fromStageId = stage.id,
576 + fromSubboardId = subboard?.id,
577 + creds = creds,
578 + dragState = dragState,
579 + onClick = { onOpenCard(c) },
580 + onDropFinished = onDropFinished,
581 + )
582 + }
583 + }
584 + } else {
585 + // Non-lazy: the whole grid scrolls, so nesting a scrollable
586 + // list here would crash with infinite height constraints.
587 + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
588 + sorted.forEach { c ->
589 + CardChip(
590 + card = c,
591 + fromStageId = stage.id,
592 + fromSubboardId = subboard?.id,
593 + creds = creds,
594 + dragState = dragState,
595 + onClick = { onOpenCard(c) },
596 + onDropFinished = onDropFinished,
597 + )
598 + }
570 599 }
571 600 }
572 601 }

Parents: f4ed124