- In Jetpack Compose
Box, children are drawn in declaration order โ the last declared child renders on top and gets touch events first. AfillMaxSize()Columndeclared after aTextButtonwill 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 โ useArrangement.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 runDELETE 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. trimToLimitSQL 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.
๐ 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