mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
ui: keep a gap before the first library tab
Put an 8dp spacer at the start of the scrollable content and let the reveal leave that gap when scrolling back towards the first tab, so the selected pill no longer sits flush against the screen edge. The spacer scrolls away, so a tab that is half off is still cut at the edge.
This commit is contained in:
@@ -830,6 +830,7 @@ private fun ListOptionsSheet(
|
||||
|
||||
private val BOTTOM_CLEARANCE = 80.dp
|
||||
private val TAB_BAR_CONTENT_HEIGHT = 52.dp
|
||||
private val TAB_STRIP_LEADING_GAP = 8.dp
|
||||
private val TAB_ICON_SIZE = 24.dp
|
||||
private val TAB_VERTICAL_PADDING = 6.dp
|
||||
private val TOUCH_TARGET = 48.dp
|
||||
@@ -903,14 +904,15 @@ internal fun LibraryTabs(
|
||||
var viewportWidth by remember { mutableIntStateOf(0) }
|
||||
var contentWidth by remember { mutableIntStateOf(0) }
|
||||
var revealed by remember { mutableStateOf(false) }
|
||||
val leadingGap = with(density) { TAB_STRIP_LEADING_GAP.toPx() }
|
||||
LaunchedEffect(pagerState.settledPage, viewportWidth, contentWidth, layoutDirection, bounds[pagerState.settledPage]) {
|
||||
if (viewportWidth == 0) return@LaunchedEffect
|
||||
val settled = bounds[pagerState.settledPage] ?: return@LaunchedEffect
|
||||
val start = if (layoutDirection == LayoutDirection.Rtl) contentWidth - settled.right else settled.left
|
||||
val end = if (layoutDirection == LayoutDirection.Rtl) contentWidth - settled.left else settled.right
|
||||
val start = if (layoutDirection == LayoutDirection.Rtl) contentWidth - settled.right else leadingGap + settled.left
|
||||
val end = if (layoutDirection == LayoutDirection.Rtl) contentWidth - settled.left else leadingGap + settled.right
|
||||
val target =
|
||||
when {
|
||||
start < scrollState.value -> start
|
||||
start - leadingGap < scrollState.value -> start - leadingGap
|
||||
end > scrollState.value + viewportWidth -> end - viewportWidth
|
||||
else -> null
|
||||
}
|
||||
@@ -939,13 +941,14 @@ internal fun LibraryTabs(
|
||||
Modifier
|
||||
.weight(1f)
|
||||
.onSizeChanged { viewportWidth = it.width }
|
||||
.horizontalScroll(scrollState),
|
||||
.horizontalScroll(scrollState)
|
||||
.onSizeChanged { contentWidth = it.width },
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Spacer(Modifier.width(TAB_STRIP_LEADING_GAP))
|
||||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
.onSizeChanged { contentWidth = it.width }
|
||||
.drawBehind {
|
||||
if (current != null &&
|
||||
indicatorLeft != null &&
|
||||
|
||||
@@ -464,6 +464,41 @@ class LibraryScreenTest {
|
||||
assertTabFullyVisible(LibraryTab.Playlists, labelWidth)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "de-rDE-w320dp-h640dp-xhdpi")
|
||||
fun returningToTheFirstTabLeavesAGapAtTheEdge() {
|
||||
val selectedTab = mutableStateOf(LibraryTab.Playlists)
|
||||
composeRule.setContent {
|
||||
SubtracksTheme {
|
||||
LibraryScreen(
|
||||
selectedTab = selectedTab.value,
|
||||
onTabSelected = { selectedTab.value = it },
|
||||
albums = remember { flowOf(PagingData.empty<Album>()) },
|
||||
artists = remember { flowOf(PagingData.empty<Artist>()) },
|
||||
playlists = remember { flowOf(PagingData.empty<Playlist>()) },
|
||||
coverArt = { _, _ -> null },
|
||||
onAlbumClick = {},
|
||||
onArtistClick = {},
|
||||
onPlaylistClick = {},
|
||||
onSync = {},
|
||||
onOpenSettings = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
composeRule.waitForIdle()
|
||||
|
||||
composeRule.runOnIdle { selectedTab.value = LibraryTab.Home }
|
||||
val expectedGap = with(composeRule.density) { TAB_EDGE_GAP.toPx() }
|
||||
composeRule.waitUntil(5_000) { tabBounds(LibraryTab.Home).left <= expectedGap + 1f }
|
||||
|
||||
assertEquals(
|
||||
"the first tab should keep a gap from the screen edge",
|
||||
expectedGap,
|
||||
tabBounds(LibraryTab.Home).left,
|
||||
1f,
|
||||
)
|
||||
}
|
||||
|
||||
private fun assertTabFullyVisible(
|
||||
tab: LibraryTab,
|
||||
labelWidth: Float,
|
||||
@@ -549,3 +584,4 @@ class LibraryScreenTest {
|
||||
}
|
||||
|
||||
private val TAB_LABEL_CHROME = 56.dp
|
||||
private val TAB_EDGE_GAP = 8.dp
|
||||
|
||||
Reference in New Issue
Block a user