From bf3312ba9e94eed0844493be1313f13807672a69 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 11 Mar 2026 19:43:34 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/core/ui/ds/TangemPagerIndicator.kt | 140 +++++++----------- 1 file changed, 52 insertions(+), 88 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt b/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt index 5528190513..ad4bc15824 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/ds/TangemPagerIndicator.kt @@ -1,5 +1,6 @@ package com.tangem.core.ui.ds +import android.content.res.Configuration import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.animateDpAsState @@ -8,6 +9,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -16,10 +18,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import com.tangem.core.ui.extensions.conditionalCompose import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreviewRedesign import kotlinx.coroutines.Job @@ -34,30 +39,31 @@ private const val MIN_HIDDEN_FOR_SMALL_DOT = 2 private const val MIN_DISTANCE_FOR_SMALL_DOT = 3 private const val MIN_DISTANCE_FOR_HINT_DOT = 2 -private val SPACING = 4.dp -private val CURRENT_DOT_SIZE = DpSize(16.dp, 8.dp) +private val SPACING = 8.dp private val NORMAL_DOT_SIZE = DpSize(8.dp, 8.dp) private val HINT_DOT_SIZE = DpSize(6.dp, 6.dp) private val SMALL_DOT_SIZE = DpSize(4.dp, 4.dp) /** - * // TODO Cleanup and document this code, it's quite complex and has some "magic numbers" that need explanation. - * * A pager indicator that adapts to the number of pages and the current page index. * + * [Figma]("https://www.figma.com/design/RU7AIgwHtGdMfy83T5UOoR/Core-Library?node-id=8452-16489&m=dev") + * * For 5 or fewer pages, it shows all dots with the current page highlighted. * For more than 5 pages, it shows a sliding window of 5 dots with size and opacity indicating position. * - * @param pagerState state of the pager to observe - * @param activeIndicatorColor color for the active page indicator + * @param pagerState state of the pager to observe + * @param modifier modifier for styling + * @param hasBackground whether to show a background behind the indicators + * @param activeIndicatorColor color for the active page indicator * @param inactiveIndicatorColor color for the inactive page indicators - * @param modifier modifier for styling */ @Suppress("LongMethod", "CyclomaticComplexMethod") @Composable fun TangemPagerIndicator( pagerState: PagerState, modifier: Modifier = Modifier, + hasBackground: Boolean = false, activeIndicatorColor: Color = TangemTheme.colors2.graphic.neutral.primary, inactiveIndicatorColor: Color = TangemTheme.colors2.graphic.neutral.tertiary, ) { @@ -124,7 +130,14 @@ fun TangemPagerIndicator( val visibleIndices = (displayLower until displayUpper).toList() Box( - modifier = modifier, + modifier = modifier + .conditionalCompose(hasBackground) { + background( + color = TangemTheme.colors2.tabs.backgroundSecondary, + shape = CircleShape, + ) + } + .padding(TangemTheme.dimens2.x3), contentAlignment = Alignment.Center, ) { Row( @@ -173,9 +186,6 @@ private fun getWindowBounds(totalPages: Int, currentIndex: Int): Pair } private fun getDotSize(index: Int, currentIndex: Int, totalPages: Int): DpSize { - if (index == currentIndex) { - return CURRENT_DOT_SIZE - } if (totalPages <= MAX_VISIBLE_DOTS) { return NORMAL_DOT_SIZE } @@ -276,95 +286,49 @@ private fun Dot( val shape = RoundedCornerShape(animatedHeight / 2) - Box( - modifier = modifier - .width(animatedWidth) - .height(animatedHeight) - .background(animatedColor, shape), - ) + Box(modifier.size(8.dp)) { + Box( + modifier = Modifier + .align(Alignment.Center) + .width(animatedWidth) + .height(animatedHeight) + .background(animatedColor, shape), + ) + } } -@Preview(showBackground = true) +// region Preview @Composable -private fun PagerIndicatorPreview() { +@Preview(showBackground = true) +@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES) +private fun TangemPagerIndicator_Preview(@PreviewParameter(TangemPagerIndicatorPreviewProvider::class) params: Int) { TangemThemePreviewRedesign { Column( Modifier - .background(TangemTheme.colors.background.primary) + .background(TangemTheme.colors2.surface.level1) .padding(20.dp), verticalArrangement = Arrangement.spacedBy(10.dp), ) { - listOf(0, 1, 2, 3, 4).forEach { page -> - TangemPagerIndicator(rememberPagerState(page) { 5 }) + repeat(params) { index -> + TangemPagerIndicator( + pagerState = rememberPagerState(index) { params }, + hasBackground = index % 2 == 0, + ) } } } } -@Preview(showBackground = true) -@Composable -private fun PagerIndicator6ItemsPreview() { - TangemThemePreviewRedesign { - Column( - Modifier - .background(TangemTheme.colors.background.primary) - .padding(20.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - listOf(0, 1, 2, 3, 4, 5).forEach { page -> - TangemPagerIndicator(rememberPagerState(page) { 6 }) - } - } - } +private class TangemPagerIndicatorPreviewProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + 1, + 2, + 3, + 5, + 6, + 7, + 10, + ) } - -@Preview(showBackground = true) -@Composable -private fun PagerIndicator7ItemsPreview() { - TangemThemePreviewRedesign { - Column( - Modifier - .background(TangemTheme.colors.background.primary) - .padding(20.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - listOf(0, 1, 2, 3, 4, 5, 6).forEach { page -> - TangemPagerIndicator(rememberPagerState(page) { 7 }) - } - } - } -} - -@Preview(showBackground = true) -@Composable -private fun PagerIndicator10ItemsPreview() { - TangemThemePreviewRedesign { - Column( - Modifier - .background(TangemTheme.colors.background.primary) - .padding(20.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).forEach { page -> - TangemPagerIndicator(rememberPagerState(page) { 10 }) - } - } - } -} - -@Preview(showBackground = true) -@Composable -private fun PagerIndicatorSmallCountsPreview() { - TangemThemePreviewRedesign { - Column( - Modifier - .background(TangemTheme.colors.background.primary) - .padding(20.dp), - verticalArrangement = Arrangement.spacedBy(10.dp), - ) { - TangemPagerIndicator(rememberPagerState(0) { 1 }) - TangemPagerIndicator(rememberPagerState(1) { 2 }) - TangemPagerIndicator(rememberPagerState(1) { 3 }) - } - } -} \ No newline at end of file +// endregion \ No newline at end of file