Young Devs Bin
๐Ÿ“ Today I Learned

Compose Box Z-Order, DB Trim Pattern, and Onboarding Layout Fixes

ยท2 min readยท#today-i-learned#android#kotlin#compose#room#ux
  • In Jetpack Compose Box, children are drawn in declaration order โ€” the last declared child renders on top and gets touch events first. A fillMaxSize() Column declared after a TextButton will silently consume all taps, making the button unreachable. Fix: move the button to be the last child so it sits on top of the scroll surface.
  • verticalArrangement = Arrangement.Center + fillMaxSize() centers all content vertically โ€” use Arrangement.Top + padding(top = N.dp) + verticalScroll(rememberScrollState()) to fill from the top and scroll if content overflows. The top padding accounts for any overlay UI (e.g., a Skip button).
  • To keep a Room table bounded without a background job, use the insert-then-trim pattern: after every INSERT, immediately run DELETE FROM table WHERE id NOT IN (SELECT id FROM table ORDER BY timestamp DESC LIMIT N). One SQL round-trip, always enforced, no scheduler needed.
  • trimToLimit SQL in Room: @Query("DELETE FROM t WHERE id NOT IN (SELECT id FROM t ORDER BY timestamp DESC LIMIT :limit)") โ€” straightforward and works even if the table is already under the limit (no-op delete).
  • A clear (ร—) button in a search field is better UX than "tap to clear" โ€” it's explicit, doesn't conflict with cursor placement, and works whether the field was filled by the user or loaded programmatically from history.
  • When seeding test data, food/recipe content is more universally readable for screenshots than developer-specific content. Always consider who sees the screenshots before picking seed content.