fix(geocaching): round the FAB, and keep the action bar off the navigation bar

Both from first contact with a real screen, and both the same root cause: I
reasoned from the Compose API instead of copying the screen next door.

The FAB used MaterialTheme.shapes.large -- a 16dp rounded rect, which at 55dp
reads as a rounded square. Every other FAB in the app uses CircleShape and the
shared Size55Modifier/Size26Modifier. NewProductButton and NewGeoNoteButton
both had it right, two directories away.

The cache detail screen's action bar sat behind the 3-button navigation.
Material3's Scaffold passes window insets to the content slot only; a bottomBar
is expected to handle its own, which the app's own DisappearingScaffold does
with a comment explaining exactly that. navigationBarsPadding now goes on the
bar's content rather than its Surface, so the background still runs to the
screen edge while the buttons clear the navigation.

Auditing for the same mistake found three more: all three ModalBottomSheets
ended with fixed-height spacers standing in for the inset, and the add-to-hunt
one used an empty Text("") as a spacer. All four now use the real inset, which
also behaves correctly under gesture navigation where the band is much smaller.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WG7T9hAHDMKPaHsWvqySEr
This commit is contained in:
Claude
2026-09-21 01:22:10 +00:00
parent 954e6a59e4
commit 9b7e38b710
5 changed files with 27 additions and 10 deletions
@@ -20,32 +20,32 @@
*/
package com.vitorpamplona.amethyst.ui.screen.loggedIn.geocaches
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
import com.vitorpamplona.amethyst.commons.resources.Res
import com.vitorpamplona.amethyst.commons.resources.geocache_hide_a_cache
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.theme.Size26Modifier
import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
import org.jetbrains.compose.resources.stringResource
@Composable
fun NewGeocacheButton(nav: INav) {
FloatingActionButton(
onClick = { nav.nav(Route.NewGeocache()) },
modifier = Modifier.size(55.dp),
shape = MaterialTheme.shapes.large,
modifier = Size55Modifier,
shape = CircleShape,
containerColor = MaterialTheme.colorScheme.primary,
) {
Icon(
symbol = MaterialSymbols.Add,
contentDescription = stringResource(Res.string.geocache_hide_a_cache),
modifier = Modifier.size(26.dp),
modifier = Size26Modifier,
tint = MaterialTheme.colorScheme.onPrimary,
)
}
@@ -24,7 +24,10 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -197,7 +200,10 @@ fun GeocacheAddToHuntSheet(
}
}
Text("", modifier = Modifier.padding(bottom = 24.dp))
// The sheet's last row has to clear the system navigation, and an empty Text was
// standing in for that. Spacer + the real inset is both honest and correct on
// gesture navigation, where the reserved band is much smaller.
Spacer(Modifier.navigationBarsPadding().height(16.dp))
}
}
}
@@ -35,6 +35,7 @@ import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
@@ -467,7 +468,15 @@ private fun GeocacheActionBar(
Surface(tonalElevation = 3.dp) {
Column(
Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 10.dp),
// navigationBarsPadding on the *content* rather than the Surface: the bar's
// background still runs to the bottom of the screen, while the buttons sit above
// the 3-button navigation instead of underneath it. Material3's Scaffold passes
// its window insets to the content slot only -- a bottomBar is expected to handle
// its own, which this one was not doing.
Modifier
.fillMaxWidth()
.navigationBarsPadding()
.padding(horizontal = 16.dp, vertical = 10.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
// The status line replaces the find buttons rather than sitting above them, so the
@@ -26,6 +26,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -140,7 +141,7 @@ fun GeocacheLogSheet(
) { Text(stringResource(Res.string.geocache_log_post)) }
}
Spacer(Modifier.height(20.dp))
Spacer(Modifier.navigationBarsPadding().height(20.dp))
}
}
}
@@ -24,6 +24,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.AlertDialog
@@ -205,7 +206,7 @@ fun GeocacheOwnerActions(
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center,
)
Spacer(Modifier.height(24.dp))
Spacer(Modifier.navigationBarsPadding().height(24.dp))
}
}
}