From 677bd279a652befce13c44637ddaa574f78cc4e7 Mon Sep 17 00:00:00 2001 From: Boonapart Date: Tue, 15 Jul 2025 11:54:07 +0300 Subject: [PATCH 1/7] Add OnboardingContainer to core --- design/api/current.api | 63 ++++++++++++++ .../models/OnboardingContainerColor.kt | 7 ++ .../models/OnboardingContainerDimens.kt | 8 ++ .../models/StepProgressBarDimens.kt | 13 +++ .../models/StepProgressColors.kt | 8 ++ .../ui/OnboardingContainer.kt | 84 +++++++++++++++++++ .../onboardingcontainer/ui/StepProgressBar.kt | 49 +++++++++++ 7 files changed, 232 insertions(+) create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressColors.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt diff --git a/design/api/current.api b/design/api/current.api index 0e9da44d..3b3da810 100644 --- a/design/api/current.api +++ b/design/api/current.api @@ -203,6 +203,69 @@ package com.urlaunched.android.design.ui.modifiers { } +package com.urlaunched.android.design.ui.onboardingcontainer.models { + + public final class OnboardingContainerColor { + ctor public OnboardingContainerColor(optional long backgroundColor); + method public long component1-0d7_KjU(); + method public com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerColor copy-8_81llA(long backgroundColor); + method public long getBackgroundColor(); + property public final long backgroundColor; + } + + public final class OnboardingContainerDimens { + ctor public OnboardingContainerDimens(optional float verticalSpacing); + method public float component1-D9Ej5fM(); + method public com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerDimens copy-0680j_4(float verticalSpacing); + method public float getVerticalSpacing(); + property public final float verticalSpacing; + } + + public final class StepProgressColors { + ctor public StepProgressColors(optional long selectedStepColor, optional long unselectedStepColor); + method public long component1-0d7_KjU(); + method public long component2-0d7_KjU(); + method public com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors copy--OWjLjI(long selectedStepColor, long unselectedStepColor); + method public long getSelectedStepColor(); + method public long getUnselectedStepColor(); + property public final long selectedStepColor; + property public final long unselectedStepColor; + } + + public final class StepProgressDimens { + ctor public StepProgressDimens(optional float containerHeight, optional float containerWidth, optional float containerShape, optional float horizontalSpacer, optional float progressBarTopSpacing); + method public float component1-D9Ej5fM(); + method public float component2-D9Ej5fM(); + method public float component3-D9Ej5fM(); + method public float component4-D9Ej5fM(); + method public float component5-D9Ej5fM(); + method public com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens copy-RyVG9vg(float containerHeight, float containerWidth, float containerShape, float horizontalSpacer, float progressBarTopSpacing); + method public float getContainerHeight(); + method public float getContainerShape(); + method public float getContainerWidth(); + method public float getHorizontalSpacer(); + method public float getProgressBarTopSpacing(); + property public final float containerHeight; + property public final float containerShape; + property public final float containerWidth; + property public final float horizontalSpacer; + property public final float progressBarTopSpacing; + } + +} + +package com.urlaunched.android.design.ui.onboardingcontainer.ui { + + public final class OnboardingContainerKt { + method @androidx.compose.runtime.Composable public static void OnboardingContainer(int activeStepIndex, int countOfSteps, androidx.compose.foundation.pager.PagerState pagerState, com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerColor onboardingContainerColor, optional com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerDimens onboardingContainerDimens, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors stepProgressColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens stepProgressDimens, kotlin.jvm.functions.Function1 imageContent, kotlin.jvm.functions.Function0 titleContent, kotlin.jvm.functions.Function0 descriptionContent, kotlin.jvm.functions.Function0 nextButtonContent, kotlin.jvm.functions.Function0 skipButtonContent, optional kotlin.jvm.functions.Function0 additionalContent); + } + + public final class StepProgressBarKt { + method @androidx.compose.runtime.Composable public static void StepProgressBar(optional androidx.compose.ui.Modifier modifier, int activeStepIndex, int countOfSteps, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors stepProgressColors, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens stepProgressDimens); + } + +} + package com.urlaunched.android.design.ui.paging { public final class PagingColumnKt { diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt new file mode 100644 index 00000000..95bf541f --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt @@ -0,0 +1,7 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.models + +import androidx.compose.ui.graphics.Color + +data class OnboardingContainerColor( + val backgroundColor: Color = Color.White +) diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt new file mode 100644 index 00000000..f88460e4 --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt @@ -0,0 +1,8 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.models + +import androidx.compose.ui.unit.Dp +import com.urlaunched.android.design.resources.dimens.Dimens + +data class OnboardingContainerDimens( + val verticalSpacing: Dp = Dimens.spacingBig +) diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt new file mode 100644 index 00000000..86c7683d --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt @@ -0,0 +1,13 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.models + +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.urlaunched.android.design.resources.dimens.Dimens + +data class StepProgressDimens( + val containerHeight: Dp = 5.dp, + val containerWidth: Dp = 24.dp, + val containerShape: Dp = 6.dp, + val horizontalSpacer: Dp = 3.dp, + val progressBarTopSpacing: Dp = Dimens.spacingLarge +) \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressColors.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressColors.kt new file mode 100644 index 00000000..5dbb705e --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressColors.kt @@ -0,0 +1,8 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.models + +import androidx.compose.ui.graphics.Color + +data class StepProgressColors( + val selectedStepColor: Color = Color.Black, + val unselectedStepColor: Color = Color.White +) diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt new file mode 100644 index 00000000..72c1df4c --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt @@ -0,0 +1,84 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerColor +import com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerDimens +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens + +@Composable +fun OnboardingContainer( + activeStepIndex: Int, + countOfSteps: Int, + pagerState: PagerState, + onboardingContainerColor: OnboardingContainerColor, + onboardingContainerDimens: OnboardingContainerDimens = OnboardingContainerDimens(), + stepProgressColors: StepProgressColors, + stepProgressDimens: StepProgressDimens = StepProgressDimens(), + imageContent: @Composable (page: Int) -> Unit, + titleContent: @Composable () -> Unit, + descriptionContent: @Composable () -> Unit, + nextButtonContent: @Composable () -> Unit, + skipButtonContent: @Composable () -> Unit, + additionalContent: @Composable () -> Unit = {} +) { + Column( + Modifier + .fillMaxSize() + .background(onboardingContainerColor.backgroundColor) + .systemBarsPadding() + .padding(vertical = onboardingContainerDimens.verticalSpacing) + ) { + HorizontalPager( + modifier = Modifier.weight(1f), + verticalAlignment = Alignment.Top, + state = pagerState + ) { page -> + Column( + modifier = Modifier, + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top + ) { + imageContent(page) + + titleContent() + + descriptionContent() + } + } + + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top + ) { + Spacer(modifier = Modifier.height(stepProgressDimens.progressBarTopSpacing)) + + StepProgressBar( + activeStepIndex = activeStepIndex, + countOfSteps = countOfSteps, + stepProgressColors = stepProgressColors, + stepProgressDimens = stepProgressDimens + ) + + nextButtonContent() + + skipButtonContent() + + additionalContent() + } + } +} \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt new file mode 100644 index 00000000..f09327d4 --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt @@ -0,0 +1,49 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.ui + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens + +@Composable +fun StepProgressBar( + modifier: Modifier = Modifier, + activeStepIndex: Int, + countOfSteps: Int, + stepProgressColors: StepProgressColors, + stepProgressDimens: StepProgressDimens +) { + Row(modifier = modifier) { + for (step in 0..countOfSteps) { + val tabTextColor = animateColorAsState( + targetValue = if (step == activeStepIndex) { + stepProgressColors.selectedStepColor + } else { + stepProgressColors.unselectedStepColor + }, + animationSpec = tween(300, easing = LinearEasing) + ) + + Box( + modifier = Modifier + .size(height = stepProgressDimens.containerHeight, width = stepProgressDimens.containerWidth) + .clip(RoundedCornerShape(stepProgressDimens.containerShape)) + .background(tabTextColor.value) + ) + + Spacer(Modifier.width(stepProgressDimens.horizontalSpacer)) + } + } +} + From 13f5e0676f27a20694ea4265e235eda7f8b2c624 Mon Sep 17 00:00:00 2001 From: Khotych Mykola Date: Tue, 30 Sep 2025 11:31:13 +0300 Subject: [PATCH 2/7] Refactor onboarding container --- .../OnboardingContainer.kt | 151 ++++++++++++++++++ .../ui/onboardingcontainer/StepProgressBar.kt | 64 ++++++++ .../constants/StepProgressBarConstants.kt | 6 + .../constants/StepProgressBarDimens.kt | 10 ++ .../models/OnboardingContainerColor.kt | 7 - .../models/OnboardingContainerDimens.kt | 8 - ...ressColors.kt => StepProgressBarColors.kt} | 6 +- .../models/StepProgressBarDimens.kt | 13 -- .../models/StepProgressBarStyle.kt | 13 ++ .../ui/OnboardingContainer.kt | 84 ---------- .../onboardingcontainer/ui/StepProgressBar.kt | 49 ------ 11 files changed, 247 insertions(+), 164 deletions(-) create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarConstants.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarDimens.kt delete mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt delete mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt rename design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/{StepProgressColors.kt => StepProgressBarColors.kt} (64%) delete mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt create mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarStyle.kt delete mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt delete mode 100644 design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt new file mode 100644 index 00000000..c1131094 --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt @@ -0,0 +1,151 @@ +package com.urlaunched.android.design.ui.onboardingcontainer + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.urlaunched.android.design.resources.dimens.Dimens +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle + +@Composable +fun OnboardingContainer( + modifier: Modifier = Modifier, + pagerState: PagerState, + stepProgressBarColors: StepProgressBarColors = StepProgressBarColors(), + stepProgressBarStyle: StepProgressBarStyle = StepProgressBarStyle(), + stepProgressPadding: PaddingValues = PaddingValues(top = Dimens.spacingNormal), + pageArrangement: Arrangement.Vertical = Arrangement.Top, + pageAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, + pageImage: @Composable ColumnScope.(page: Int) -> Unit, + pageTitle: @Composable ColumnScope.(page: Int) -> Unit, + pageDescription: @Composable ColumnScope.(page: Int) -> Unit, + nextButton: @Composable ColumnScope.() -> Unit, + skipButton: @Composable ColumnScope.() -> Unit, + additionalContent: @Composable ColumnScope.() -> Unit = {} +) { + Column( + modifier = modifier + ) { + HorizontalPager( + modifier = Modifier.weight(1f), + verticalAlignment = Alignment.Top, + state = pagerState + ) { page -> + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = pageAlignment, + verticalArrangement = pageArrangement + ) { + pageImage(page) + + pageTitle(page) + + pageDescription(page) + } + } + + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + StepProgressBar( + activeStepIndex = pagerState.currentPage, + stepsCount = pagerState.pageCount, + stepProgressBarColors = stepProgressBarColors, + stepProgressBarStyle = stepProgressBarStyle, + modifier = Modifier.padding(stepProgressPadding) + ) + + nextButton() + + skipButton() + + additionalContent() + } + } +} + +@Preview(showBackground = true) +@Composable +private fun OnboardingContainerPreview() { + val pagerState = rememberPagerState(pageCount = { 4 }) + + OnboardingContainer( + pagerState = pagerState, + pageImage = { page -> + Box( + modifier = Modifier + .padding(top = 100.dp) + .size(270.dp) + .background(Color(0xFF4CAF50), RoundedCornerShape(24.dp)) + ) + }, + pageTitle = { + Text( + text = "Welcome to the App", + style = MaterialTheme.typography.displaySmall, + modifier = Modifier.padding(top = 32.dp) + ) + }, + pageDescription = { + Text( + text = "Your go-to application for everything.\nEmbark on an exciting journey with us.", + style = MaterialTheme.typography.labelLarge, + textAlign = TextAlign.Center, + color = Color(0xA3000000), + modifier = Modifier.padding(top = 8.dp) + ) + }, + nextButton = { + Button( + onClick = {}, + modifier = Modifier + .padding(top = Dimens.spacingBig) + .width(200.dp) + ) { + Text("Next") + } + }, + stepProgressBarColors = StepProgressBarColors( + selectedStepColor = MaterialTheme.colorScheme.primary, + unselectedStepColor = MaterialTheme.colorScheme.primaryContainer + ), + skipButton = { + TextButton( + onClick = {}, + modifier = Modifier.width(200.dp) + ) { + Text("Skip") + } + }, + additionalContent = { + Text( + text = "Privacy Policy, Terms & Conditions", + modifier = Modifier.padding(vertical = Dimens.spacingNormal) + ) + } + ) +} \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt new file mode 100644 index 00000000..d7b92454 --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt @@ -0,0 +1,64 @@ +package com.urlaunched.android.design.ui.onboardingcontainer + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.urlaunched.android.design.ui.onboardingcontainer.constants.StepProgressBarConstants +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors +import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle + +@Composable +fun StepProgressBar( + modifier: Modifier = Modifier, + activeStepIndex: Int, + stepsCount: Int, + stepProgressBarColors: StepProgressBarColors, + stepProgressBarStyle: StepProgressBarStyle +) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(stepProgressBarStyle.stepsSpacing) + ) { + for (stepIndex in StepProgressBarConstants.PROGRESS_BAR_FIRST_STEP until stepsCount) { + val tabColor by animateColorAsState( + targetValue = if (stepIndex == activeStepIndex) { + stepProgressBarColors.selectedStepColor + } else { + stepProgressBarColors.unselectedStepColor + }, + animationSpec = tween(StepProgressBarConstants.STEP_COLOR_ANIM_DURATION_MILLIS, easing = LinearEasing) + ) + + Box( + modifier = Modifier + .size(height = stepProgressBarStyle.stepHeight, width = stepProgressBarStyle.stepWidth) + .clip(stepProgressBarStyle.stepShape) + .background(tabColor) + ) + } + } +} + +@Preview(showBackground = true) +@Composable +private fun StepProgressBarPreview() { + StepProgressBar( + modifier = Modifier.padding(16.dp), + activeStepIndex = 1, + stepsCount = 4, + stepProgressBarColors = StepProgressBarColors(), + stepProgressBarStyle = StepProgressBarStyle() + ) +} \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarConstants.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarConstants.kt new file mode 100644 index 00000000..d7c0d1c7 --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarConstants.kt @@ -0,0 +1,6 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.constants + +internal object StepProgressBarConstants { + const val PROGRESS_BAR_FIRST_STEP = 0 + const val STEP_COLOR_ANIM_DURATION_MILLIS = 300 +} \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarDimens.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarDimens.kt new file mode 100644 index 00000000..d8184e9e --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarDimens.kt @@ -0,0 +1,10 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.constants + +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +internal object StepProgressBarDimens { + val defaultStepHeight: Dp = 5.dp + val defaultStepWidth: Dp = 24.dp + val defaultStepsSpacing: Dp = 4.dp +} \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt deleted file mode 100644 index 95bf541f..00000000 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerColor.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.urlaunched.android.design.ui.onboardingcontainer.models - -import androidx.compose.ui.graphics.Color - -data class OnboardingContainerColor( - val backgroundColor: Color = Color.White -) diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt deleted file mode 100644 index f88460e4..00000000 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/OnboardingContainerDimens.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.urlaunched.android.design.ui.onboardingcontainer.models - -import androidx.compose.ui.unit.Dp -import com.urlaunched.android.design.resources.dimens.Dimens - -data class OnboardingContainerDimens( - val verticalSpacing: Dp = Dimens.spacingBig -) diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressColors.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarColors.kt similarity index 64% rename from design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressColors.kt rename to design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarColors.kt index 5dbb705e..3baa1b49 100644 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressColors.kt +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarColors.kt @@ -2,7 +2,7 @@ package com.urlaunched.android.design.ui.onboardingcontainer.models import androidx.compose.ui.graphics.Color -data class StepProgressColors( +data class StepProgressBarColors( val selectedStepColor: Color = Color.Black, - val unselectedStepColor: Color = Color.White -) + val unselectedStepColor: Color = Color.LightGray +) \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt deleted file mode 100644 index 86c7683d..00000000 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarDimens.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.urlaunched.android.design.ui.onboardingcontainer.models - -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.urlaunched.android.design.resources.dimens.Dimens - -data class StepProgressDimens( - val containerHeight: Dp = 5.dp, - val containerWidth: Dp = 24.dp, - val containerShape: Dp = 6.dp, - val horizontalSpacer: Dp = 3.dp, - val progressBarTopSpacing: Dp = Dimens.spacingLarge -) \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarStyle.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarStyle.kt new file mode 100644 index 00000000..4a19ad99 --- /dev/null +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/models/StepProgressBarStyle.kt @@ -0,0 +1,13 @@ +package com.urlaunched.android.design.ui.onboardingcontainer.models + +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp +import com.urlaunched.android.design.ui.onboardingcontainer.constants.StepProgressBarDimens + +data class StepProgressBarStyle( + val stepHeight: Dp = StepProgressBarDimens.defaultStepHeight, + val stepWidth: Dp = StepProgressBarDimens.defaultStepWidth, + val stepsSpacing: Dp = StepProgressBarDimens.defaultStepsSpacing, + val stepShape: Shape = CircleShape +) \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt deleted file mode 100644 index 72c1df4c..00000000 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/OnboardingContainer.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.urlaunched.android.design.ui.onboardingcontainer.ui - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.systemBarsPadding -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.PagerState -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerColor -import com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerDimens -import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors -import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens - -@Composable -fun OnboardingContainer( - activeStepIndex: Int, - countOfSteps: Int, - pagerState: PagerState, - onboardingContainerColor: OnboardingContainerColor, - onboardingContainerDimens: OnboardingContainerDimens = OnboardingContainerDimens(), - stepProgressColors: StepProgressColors, - stepProgressDimens: StepProgressDimens = StepProgressDimens(), - imageContent: @Composable (page: Int) -> Unit, - titleContent: @Composable () -> Unit, - descriptionContent: @Composable () -> Unit, - nextButtonContent: @Composable () -> Unit, - skipButtonContent: @Composable () -> Unit, - additionalContent: @Composable () -> Unit = {} -) { - Column( - Modifier - .fillMaxSize() - .background(onboardingContainerColor.backgroundColor) - .systemBarsPadding() - .padding(vertical = onboardingContainerDimens.verticalSpacing) - ) { - HorizontalPager( - modifier = Modifier.weight(1f), - verticalAlignment = Alignment.Top, - state = pagerState - ) { page -> - Column( - modifier = Modifier, - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Top - ) { - imageContent(page) - - titleContent() - - descriptionContent() - } - } - - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Top - ) { - Spacer(modifier = Modifier.height(stepProgressDimens.progressBarTopSpacing)) - - StepProgressBar( - activeStepIndex = activeStepIndex, - countOfSteps = countOfSteps, - stepProgressColors = stepProgressColors, - stepProgressDimens = stepProgressDimens - ) - - nextButtonContent() - - skipButtonContent() - - additionalContent() - } - } -} \ No newline at end of file diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt deleted file mode 100644 index f09327d4..00000000 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/ui/StepProgressBar.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.urlaunched.android.design.ui.onboardingcontainer.ui - -import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.tween -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors -import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens - -@Composable -fun StepProgressBar( - modifier: Modifier = Modifier, - activeStepIndex: Int, - countOfSteps: Int, - stepProgressColors: StepProgressColors, - stepProgressDimens: StepProgressDimens -) { - Row(modifier = modifier) { - for (step in 0..countOfSteps) { - val tabTextColor = animateColorAsState( - targetValue = if (step == activeStepIndex) { - stepProgressColors.selectedStepColor - } else { - stepProgressColors.unselectedStepColor - }, - animationSpec = tween(300, easing = LinearEasing) - ) - - Box( - modifier = Modifier - .size(height = stepProgressDimens.containerHeight, width = stepProgressDimens.containerWidth) - .clip(RoundedCornerShape(stepProgressDimens.containerShape)) - .background(tabTextColor.value) - ) - - Spacer(Modifier.width(stepProgressDimens.horizontalSpacer)) - } - } -} - From ac376051139ceabc0e24a9a668d520318f24286e Mon Sep 17 00:00:00 2001 From: Khotych Mykola Date: Tue, 30 Sep 2025 11:32:38 +0300 Subject: [PATCH 3/7] Update api --- design/api/current.api | 67 +++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 43 deletions(-) diff --git a/design/api/current.api b/design/api/current.api index 3b3da810..8e074d60 100644 --- a/design/api/current.api +++ b/design/api/current.api @@ -203,65 +203,46 @@ package com.urlaunched.android.design.ui.modifiers { } -package com.urlaunched.android.design.ui.onboardingcontainer.models { +package com.urlaunched.android.design.ui.onboardingcontainer { - public final class OnboardingContainerColor { - ctor public OnboardingContainerColor(optional long backgroundColor); - method public long component1-0d7_KjU(); - method public com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerColor copy-8_81llA(long backgroundColor); - method public long getBackgroundColor(); - property public final long backgroundColor; + public final class OnboardingContainerKt { + method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.foundation.pager.PagerState pagerState, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical pageArrangement, optional androidx.compose.ui.Alignment.Horizontal pageAlignment, kotlin.jvm.functions.Function2 pageImage, kotlin.jvm.functions.Function2 pageTitle, kotlin.jvm.functions.Function2 pageDescription, kotlin.jvm.functions.Function1 nextButton, kotlin.jvm.functions.Function1 skipButton, optional kotlin.jvm.functions.Function1 additionalContent); } - public final class OnboardingContainerDimens { - ctor public OnboardingContainerDimens(optional float verticalSpacing); - method public float component1-D9Ej5fM(); - method public com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerDimens copy-0680j_4(float verticalSpacing); - method public float getVerticalSpacing(); - property public final float verticalSpacing; + public final class StepProgressBarKt { + method @androidx.compose.runtime.Composable public static void StepProgressBar(optional androidx.compose.ui.Modifier modifier, int activeStepIndex, int stepsCount, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle); } - public final class StepProgressColors { - ctor public StepProgressColors(optional long selectedStepColor, optional long unselectedStepColor); +} + +package com.urlaunched.android.design.ui.onboardingcontainer.models { + + public final class StepProgressBarColors { + ctor public StepProgressBarColors(optional long selectedStepColor, optional long unselectedStepColor); method public long component1-0d7_KjU(); method public long component2-0d7_KjU(); - method public com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors copy--OWjLjI(long selectedStepColor, long unselectedStepColor); + method public com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors copy--OWjLjI(long selectedStepColor, long unselectedStepColor); method public long getSelectedStepColor(); method public long getUnselectedStepColor(); property public final long selectedStepColor; property public final long unselectedStepColor; } - public final class StepProgressDimens { - ctor public StepProgressDimens(optional float containerHeight, optional float containerWidth, optional float containerShape, optional float horizontalSpacer, optional float progressBarTopSpacing); + public final class StepProgressBarStyle { + ctor public StepProgressBarStyle(optional float stepHeight, optional float stepWidth, optional float stepsSpacing, optional androidx.compose.ui.graphics.Shape stepShape); method public float component1-D9Ej5fM(); method public float component2-D9Ej5fM(); method public float component3-D9Ej5fM(); - method public float component4-D9Ej5fM(); - method public float component5-D9Ej5fM(); - method public com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens copy-RyVG9vg(float containerHeight, float containerWidth, float containerShape, float horizontalSpacer, float progressBarTopSpacing); - method public float getContainerHeight(); - method public float getContainerShape(); - method public float getContainerWidth(); - method public float getHorizontalSpacer(); - method public float getProgressBarTopSpacing(); - property public final float containerHeight; - property public final float containerShape; - property public final float containerWidth; - property public final float horizontalSpacer; - property public final float progressBarTopSpacing; - } - -} - -package com.urlaunched.android.design.ui.onboardingcontainer.ui { - - public final class OnboardingContainerKt { - method @androidx.compose.runtime.Composable public static void OnboardingContainer(int activeStepIndex, int countOfSteps, androidx.compose.foundation.pager.PagerState pagerState, com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerColor onboardingContainerColor, optional com.urlaunched.android.design.ui.onboardingcontainer.models.OnboardingContainerDimens onboardingContainerDimens, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors stepProgressColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens stepProgressDimens, kotlin.jvm.functions.Function1 imageContent, kotlin.jvm.functions.Function0 titleContent, kotlin.jvm.functions.Function0 descriptionContent, kotlin.jvm.functions.Function0 nextButtonContent, kotlin.jvm.functions.Function0 skipButtonContent, optional kotlin.jvm.functions.Function0 additionalContent); - } - - public final class StepProgressBarKt { - method @androidx.compose.runtime.Composable public static void StepProgressBar(optional androidx.compose.ui.Modifier modifier, int activeStepIndex, int countOfSteps, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressColors stepProgressColors, com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressDimens stepProgressDimens); + method public androidx.compose.ui.graphics.Shape component4(); + method public com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle copy-DRUOcmI(float stepHeight, float stepWidth, float stepsSpacing, androidx.compose.ui.graphics.Shape stepShape); + method public float getStepHeight(); + method public androidx.compose.ui.graphics.Shape getStepShape(); + method public float getStepWidth(); + method public float getStepsSpacing(); + property public final float stepHeight; + property public final androidx.compose.ui.graphics.Shape stepShape; + property public final float stepWidth; + property public final float stepsSpacing; } } From 6debc55d3bfc4207618a3fe368934ddcc43a8caf Mon Sep 17 00:00:00 2001 From: Khotych Mykola Date: Mon, 6 Oct 2025 17:24:35 +0300 Subject: [PATCH 4/7] Use single lambda for page content --- .../OnboardingContainer.kt | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt index c1131094..80404338 100644 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt @@ -37,11 +37,9 @@ fun OnboardingContainer( stepProgressBarColors: StepProgressBarColors = StepProgressBarColors(), stepProgressBarStyle: StepProgressBarStyle = StepProgressBarStyle(), stepProgressPadding: PaddingValues = PaddingValues(top = Dimens.spacingNormal), - pageArrangement: Arrangement.Vertical = Arrangement.Top, - pageAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, - pageImage: @Composable ColumnScope.(page: Int) -> Unit, - pageTitle: @Composable ColumnScope.(page: Int) -> Unit, - pageDescription: @Composable ColumnScope.(page: Int) -> Unit, + contentArrangement: Arrangement.Vertical = Arrangement.Top, + contentAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, + pageContent: @Composable ColumnScope.(page: Int) -> Unit, nextButton: @Composable ColumnScope.() -> Unit, skipButton: @Composable ColumnScope.() -> Unit, additionalContent: @Composable ColumnScope.() -> Unit = {} @@ -56,14 +54,10 @@ fun OnboardingContainer( ) { page -> Column( modifier = Modifier.fillMaxSize(), - horizontalAlignment = pageAlignment, - verticalArrangement = pageArrangement + horizontalAlignment = contentAlignment, + verticalArrangement = contentArrangement ) { - pageImage(page) - - pageTitle(page) - - pageDescription(page) + pageContent(page) } } @@ -95,22 +89,20 @@ private fun OnboardingContainerPreview() { OnboardingContainer( pagerState = pagerState, - pageImage = { page -> + pageContent = { page -> Box( modifier = Modifier .padding(top = 100.dp) .size(270.dp) .background(Color(0xFF4CAF50), RoundedCornerShape(24.dp)) ) - }, - pageTitle = { + Text( text = "Welcome to the App", style = MaterialTheme.typography.displaySmall, modifier = Modifier.padding(top = 32.dp) ) - }, - pageDescription = { + Text( text = "Your go-to application for everything.\nEmbark on an exciting journey with us.", style = MaterialTheme.typography.labelLarge, From ead9a4a7d42babfb6304d1e1a9495d942e0e99ca Mon Sep 17 00:00:00 2001 From: Khotych Mykola Date: Mon, 6 Oct 2025 18:27:59 +0300 Subject: [PATCH 5/7] Add onboarding container overload with list of items --- .../OnboardingContainer.kt | 66 +++++++++++++++++++ .../ui/onboardingcontainer/StepProgressBar.kt | 6 +- ...BarConstants.kt => OnboardingConstants.kt} | 4 +- 3 files changed, 71 insertions(+), 5 deletions(-) rename design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/{StepProgressBarConstants.kt => OnboardingConstants.kt} (54%) diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt index 80404338..7b98ef42 100644 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt @@ -1,5 +1,6 @@ package com.urlaunched.android.design.ui.onboardingcontainer +import androidx.compose.animation.core.TweenSpec import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -20,6 +21,8 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -27,8 +30,71 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.urlaunched.android.design.resources.dimens.Dimens +import com.urlaunched.android.design.ui.onboardingcontainer.constants.OnboardingConstants import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle +import kotlinx.coroutines.launch + +private const val FIRST_PAGE_INDEX = 0 +private const val ONE_PAGE = 1 + +@Composable +fun OnboardingContainer( + modifier: Modifier = Modifier, + pages: List, + initialPageIndex: Int = FIRST_PAGE_INDEX, + stepProgressBarColors: StepProgressBarColors = StepProgressBarColors(), + stepProgressBarStyle: StepProgressBarStyle = StepProgressBarStyle(), + stepProgressPadding: PaddingValues = PaddingValues(top = Dimens.spacingNormal), + contentArrangement: Arrangement.Vertical = Arrangement.Top, + contentAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, + onPageChange: ((page: T) -> Unit)? = null, + nextButton: @Composable ColumnScope.(page: T, isLastPage: Boolean, nextPage: () -> Unit) -> Unit, + skipButton: @Composable ColumnScope.(isLastPage: Boolean) -> Unit, + additionalContent: @Composable ColumnScope.() -> Unit = {}, + pageContent: @Composable ColumnScope.(page: T) -> Unit +) { + val coroutineScope = rememberCoroutineScope() + val pagerState = rememberPagerState( + initialPage = initialPageIndex, + pageCount = { pages.size } + ) + + onPageChange?.let { onChange -> + LaunchedEffect(pagerState.currentPage) { + onChange(pages[pagerState.currentPage]) + } + } + + val goToNextPage: () -> Unit = { + coroutineScope.launch { + pagerState.animateScrollToPage( + page = pagerState.currentPage + ONE_PAGE, + animationSpec = TweenSpec(durationMillis = OnboardingConstants.PAGE_ANIMATION_DURATION_MILLIS) + ) + } + } + + OnboardingContainer( + modifier = modifier, + pagerState = pagerState, + stepProgressBarColors = stepProgressBarColors, + stepProgressBarStyle = stepProgressBarStyle, + stepProgressPadding = stepProgressPadding, + contentArrangement = contentArrangement, + contentAlignment = contentAlignment, + pageContent = { pageIndex -> + pageContent(pages[pageIndex]) + }, + nextButton = { + nextButton(pages[pagerState.currentPage], pagerState.currentPage == pages.lastIndex, goToNextPage) + }, + skipButton = { + skipButton(pagerState.currentPage == pages.lastIndex) + }, + additionalContent = additionalContent + ) +} @Composable fun OnboardingContainer( diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt index d7b92454..f3e5ec31 100644 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/StepProgressBar.kt @@ -15,7 +15,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.urlaunched.android.design.ui.onboardingcontainer.constants.StepProgressBarConstants +import com.urlaunched.android.design.ui.onboardingcontainer.constants.OnboardingConstants import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors import com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle @@ -31,14 +31,14 @@ fun StepProgressBar( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(stepProgressBarStyle.stepsSpacing) ) { - for (stepIndex in StepProgressBarConstants.PROGRESS_BAR_FIRST_STEP until stepsCount) { + for (stepIndex in OnboardingConstants.PROGRESS_BAR_FIRST_STEP until stepsCount) { val tabColor by animateColorAsState( targetValue = if (stepIndex == activeStepIndex) { stepProgressBarColors.selectedStepColor } else { stepProgressBarColors.unselectedStepColor }, - animationSpec = tween(StepProgressBarConstants.STEP_COLOR_ANIM_DURATION_MILLIS, easing = LinearEasing) + animationSpec = tween(OnboardingConstants.PAGE_ANIMATION_DURATION_MILLIS, easing = LinearEasing) ) Box( diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarConstants.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/OnboardingConstants.kt similarity index 54% rename from design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarConstants.kt rename to design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/OnboardingConstants.kt index d7c0d1c7..dd78b619 100644 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/StepProgressBarConstants.kt +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/constants/OnboardingConstants.kt @@ -1,6 +1,6 @@ package com.urlaunched.android.design.ui.onboardingcontainer.constants -internal object StepProgressBarConstants { +internal object OnboardingConstants { const val PROGRESS_BAR_FIRST_STEP = 0 - const val STEP_COLOR_ANIM_DURATION_MILLIS = 300 + const val PAGE_ANIMATION_DURATION_MILLIS = 300 } \ No newline at end of file From 380fa84ed0baafdc5deec823327fe3b4d270c36c Mon Sep 17 00:00:00 2001 From: Khotych Mykola Date: Mon, 6 Oct 2025 18:29:39 +0300 Subject: [PATCH 6/7] Update api --- design/api/current.api | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/design/api/current.api b/design/api/current.api index 8e074d60..33fd7891 100644 --- a/design/api/current.api +++ b/design/api/current.api @@ -206,7 +206,8 @@ package com.urlaunched.android.design.ui.modifiers { package com.urlaunched.android.design.ui.onboardingcontainer { public final class OnboardingContainerKt { - method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.foundation.pager.PagerState pagerState, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical pageArrangement, optional androidx.compose.ui.Alignment.Horizontal pageAlignment, kotlin.jvm.functions.Function2 pageImage, kotlin.jvm.functions.Function2 pageTitle, kotlin.jvm.functions.Function2 pageDescription, kotlin.jvm.functions.Function1 nextButton, kotlin.jvm.functions.Function1 skipButton, optional kotlin.jvm.functions.Function1 additionalContent); + method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.foundation.pager.PagerState pagerState, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical contentArrangement, optional androidx.compose.ui.Alignment.Horizontal contentAlignment, kotlin.jvm.functions.Function2 pageContent, kotlin.jvm.functions.Function1 nextButton, kotlin.jvm.functions.Function1 skipButton, optional kotlin.jvm.functions.Function1 additionalContent); + method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, java.util.List pages, optional int initialPageIndex, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical contentArrangement, optional androidx.compose.ui.Alignment.Horizontal contentAlignment, optional kotlin.jvm.functions.Function1? onPageChange, kotlin.jvm.functions.Function4,kotlin.Unit> nextButton, kotlin.jvm.functions.Function2 skipButton, optional kotlin.jvm.functions.Function1 additionalContent, kotlin.jvm.functions.Function2 pageContent); } public final class StepProgressBarKt { From 1ba933d373e8a19733c19b7c3061f341a4b0b9c3 Mon Sep 17 00:00:00 2001 From: Khotych Mykola Date: Tue, 7 Oct 2025 13:48:38 +0300 Subject: [PATCH 7/7] Combine separate button lambdas into a single footer lambda --- design/api/current.api | 4 +- .../OnboardingContainer.kt | 42 +++++++------------ 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/design/api/current.api b/design/api/current.api index 33fd7891..b175bfa8 100644 --- a/design/api/current.api +++ b/design/api/current.api @@ -206,8 +206,8 @@ package com.urlaunched.android.design.ui.modifiers { package com.urlaunched.android.design.ui.onboardingcontainer { public final class OnboardingContainerKt { - method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.foundation.pager.PagerState pagerState, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical contentArrangement, optional androidx.compose.ui.Alignment.Horizontal contentAlignment, kotlin.jvm.functions.Function2 pageContent, kotlin.jvm.functions.Function1 nextButton, kotlin.jvm.functions.Function1 skipButton, optional kotlin.jvm.functions.Function1 additionalContent); - method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, java.util.List pages, optional int initialPageIndex, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical contentArrangement, optional androidx.compose.ui.Alignment.Horizontal contentAlignment, optional kotlin.jvm.functions.Function1? onPageChange, kotlin.jvm.functions.Function4,kotlin.Unit> nextButton, kotlin.jvm.functions.Function2 skipButton, optional kotlin.jvm.functions.Function1 additionalContent, kotlin.jvm.functions.Function2 pageContent); + method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, androidx.compose.foundation.pager.PagerState pagerState, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical contentArrangement, optional androidx.compose.ui.Alignment.Horizontal contentAlignment, kotlin.jvm.functions.Function1 footerContent, kotlin.jvm.functions.Function2 pageContent); + method @androidx.compose.runtime.Composable public static void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, java.util.List pages, optional int initialPageIndex, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarColors stepProgressBarColors, optional com.urlaunched.android.design.ui.onboardingcontainer.models.StepProgressBarStyle stepProgressBarStyle, optional androidx.compose.foundation.layout.PaddingValues stepProgressPadding, optional androidx.compose.foundation.layout.Arrangement.Vertical contentArrangement, optional androidx.compose.ui.Alignment.Horizontal contentAlignment, optional kotlin.jvm.functions.Function1? onPageChange, kotlin.jvm.functions.Function4,kotlin.Unit> footerContent, kotlin.jvm.functions.Function2 pageContent); } public final class StepProgressBarKt { diff --git a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt index 7b98ef42..d5470b98 100644 --- a/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt +++ b/design/src/main/java/com/urlaunched/android/design/ui/onboardingcontainer/OnboardingContainer.kt @@ -49,9 +49,7 @@ fun OnboardingContainer( contentArrangement: Arrangement.Vertical = Arrangement.Top, contentAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, onPageChange: ((page: T) -> Unit)? = null, - nextButton: @Composable ColumnScope.(page: T, isLastPage: Boolean, nextPage: () -> Unit) -> Unit, - skipButton: @Composable ColumnScope.(isLastPage: Boolean) -> Unit, - additionalContent: @Composable ColumnScope.() -> Unit = {}, + footerContent: @Composable ColumnScope.(page: T, isLastPage: Boolean, nextPage: () -> Unit) -> Unit, pageContent: @Composable ColumnScope.(page: T) -> Unit ) { val coroutineScope = rememberCoroutineScope() @@ -86,13 +84,9 @@ fun OnboardingContainer( pageContent = { pageIndex -> pageContent(pages[pageIndex]) }, - nextButton = { - nextButton(pages[pagerState.currentPage], pagerState.currentPage == pages.lastIndex, goToNextPage) - }, - skipButton = { - skipButton(pagerState.currentPage == pages.lastIndex) - }, - additionalContent = additionalContent + footerContent = { + footerContent(pages[pagerState.currentPage], pagerState.currentPage == pages.lastIndex, goToNextPage) + } ) } @@ -105,10 +99,8 @@ fun OnboardingContainer( stepProgressPadding: PaddingValues = PaddingValues(top = Dimens.spacingNormal), contentArrangement: Arrangement.Vertical = Arrangement.Top, contentAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, - pageContent: @Composable ColumnScope.(page: Int) -> Unit, - nextButton: @Composable ColumnScope.() -> Unit, - skipButton: @Composable ColumnScope.() -> Unit, - additionalContent: @Composable ColumnScope.() -> Unit = {} + footerContent: @Composable ColumnScope.() -> Unit, + pageContent: @Composable ColumnScope.(page: Int) -> Unit ) { Column( modifier = modifier @@ -139,11 +131,7 @@ fun OnboardingContainer( modifier = Modifier.padding(stepProgressPadding) ) - nextButton() - - skipButton() - - additionalContent() + footerContent() } } } @@ -155,6 +143,10 @@ private fun OnboardingContainerPreview() { OnboardingContainer( pagerState = pagerState, + stepProgressBarColors = StepProgressBarColors( + selectedStepColor = MaterialTheme.colorScheme.primary, + unselectedStepColor = MaterialTheme.colorScheme.primaryContainer + ), pageContent = { page -> Box( modifier = Modifier @@ -177,7 +169,7 @@ private fun OnboardingContainerPreview() { modifier = Modifier.padding(top = 8.dp) ) }, - nextButton = { + footerContent = { Button( onClick = {}, modifier = Modifier @@ -186,20 +178,14 @@ private fun OnboardingContainerPreview() { ) { Text("Next") } - }, - stepProgressBarColors = StepProgressBarColors( - selectedStepColor = MaterialTheme.colorScheme.primary, - unselectedStepColor = MaterialTheme.colorScheme.primaryContainer - ), - skipButton = { + TextButton( onClick = {}, modifier = Modifier.width(200.dp) ) { Text("Skip") } - }, - additionalContent = { + Text( text = "Privacy Policy, Terms & Conditions", modifier = Modifier.padding(vertical = Dimens.spacingNormal)