Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions design/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,51 @@ 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.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> footerContent, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ColumnScope,? super java.lang.Integer,kotlin.Unit> pageContent);
method @androidx.compose.runtime.Composable public static <T> void OnboardingContainer(optional androidx.compose.ui.Modifier modifier, java.util.List<? extends T> 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<? super T,kotlin.Unit>? onPageChange, kotlin.jvm.functions.Function4<? super androidx.compose.foundation.layout.ColumnScope,? super T,? super java.lang.Boolean,? super kotlin.jvm.functions.Function0<kotlin.Unit>,kotlin.Unit> footerContent, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.layout.ColumnScope,? super T,kotlin.Unit> pageContent);
}

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);
}

}

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.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 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 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;
}

}

package com.urlaunched.android.design.ui.paging {

public final class PagingColumnKt {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
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
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.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
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.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 <T> OnboardingContainer(
modifier: Modifier = Modifier,
pages: List<T>,
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,
footerContent: @Composable ColumnScope.(page: T, isLastPage: Boolean, nextPage: () -> Unit) -> 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])
},
footerContent = {
footerContent(pages[pagerState.currentPage], pagerState.currentPage == pages.lastIndex, goToNextPage)
}
)
}

@Composable
fun OnboardingContainer(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем этот вариант с pagerState?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Якщо потрібно буде контролювати цей стан, можливо якась інша імплементація, можна напевно додати до нього теж Base

modifier: Modifier = Modifier,
pagerState: PagerState,
stepProgressBarColors: StepProgressBarColors = StepProgressBarColors(),
stepProgressBarStyle: StepProgressBarStyle = StepProgressBarStyle(),
stepProgressPadding: PaddingValues = PaddingValues(top = Dimens.spacingNormal),
contentArrangement: Arrangement.Vertical = Arrangement.Top,
contentAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
footerContent: @Composable ColumnScope.() -> Unit,
pageContent: @Composable ColumnScope.(page: Int) -> Unit
) {
Column(
modifier = modifier
) {
HorizontalPager(
modifier = Modifier.weight(1f),
verticalAlignment = Alignment.Top,
state = pagerState
) { page ->
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = contentAlignment,
verticalArrangement = contentArrangement
) {
pageContent(page)
}
}

Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
StepProgressBar(
activeStepIndex = pagerState.currentPage,
stepsCount = pagerState.pageCount,
stepProgressBarColors = stepProgressBarColors,
stepProgressBarStyle = stepProgressBarStyle,
modifier = Modifier.padding(stepProgressPadding)
)

footerContent()
}
}
}

@Preview(showBackground = true)
@Composable
private fun OnboardingContainerPreview() {
val pagerState = rememberPagerState(pageCount = { 4 })

OnboardingContainer(
pagerState = pagerState,
stepProgressBarColors = StepProgressBarColors(
selectedStepColor = MaterialTheme.colorScheme.primary,
unselectedStepColor = MaterialTheme.colorScheme.primaryContainer
),
pageContent = { page ->
Box(
modifier = Modifier
.padding(top = 100.dp)
.size(270.dp)
.background(Color(0xFF4CAF50), RoundedCornerShape(24.dp))
)

Text(
text = "Welcome to the App",
style = MaterialTheme.typography.displaySmall,
modifier = Modifier.padding(top = 32.dp)
)

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)
)
},
footerContent = {
Button(
onClick = {},
modifier = Modifier
.padding(top = Dimens.spacingBig)
.width(200.dp)
) {
Text("Next")
}

TextButton(
onClick = {},
modifier = Modifier.width(200.dp)
) {
Text("Skip")
}

Text(
text = "Privacy Policy, Terms & Conditions",
modifier = Modifier.padding(vertical = Dimens.spacingNormal)
)
}
)
}
Original file line number Diff line number Diff line change
@@ -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.OnboardingConstants
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 OnboardingConstants.PROGRESS_BAR_FIRST_STEP until stepsCount) {
val tabColor by animateColorAsState(
targetValue = if (stepIndex == activeStepIndex) {
stepProgressBarColors.selectedStepColor
} else {
stepProgressBarColors.unselectedStepColor
},
animationSpec = tween(OnboardingConstants.PAGE_ANIMATION_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()
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.urlaunched.android.design.ui.onboardingcontainer.constants

internal object OnboardingConstants {
const val PROGRESS_BAR_FIRST_STEP = 0
const val PAGE_ANIMATION_DURATION_MILLIS = 300
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.urlaunched.android.design.ui.onboardingcontainer.models

import androidx.compose.ui.graphics.Color

data class StepProgressBarColors(
val selectedStepColor: Color = Color.Black,
val unselectedStepColor: Color = Color.LightGray
)
Original file line number Diff line number Diff line change
@@ -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
)