Jetpack Compose code for an onboarding screen featuring asynchronous image loading, customizable title, subtitle, button, and pagination indicators. Utilizes modern UI components and layouts for a dynamic user experience.
This Jetpack Compose tutorial showcases a streamlined onboarding screen, crucial for engaging and guiding new users through an app’s features.
Onboarding screens are introductory screens users encounter when launching an app for the first time, designed to familiarize them with the app’s features and functionalities. They aim to guide users through the initial setup, highlight key app benefits, and enhance user engagement, ultimately improving user retention and satisfaction.
@Composable
fun OnboardingPage(onboarding: OnboardingModel.Screen?, onClick: () -> Unit, totalItems: Int, currentPos: Int) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
// Rest of the below code snippets till page indicator will go here
}
}
This is a Composable function named OnboardingPage that takes four parameters:
onboarding: An optional OnboardingModel.Screen object containing details for the onboarding screen.onClick: A lambda function to be called when the “Next” button is clicked.totalItems: Total number of onboarding screens.currentPos: Current position or index of the onboarding screen.This creates a Column layout with the following modifiers:
fillMaxSize(): Fills the available space.padding(16.dp): Adds 16dp padding around the column.AsyncImage(
model = onboarding?.imageUrl,
contentDescription = "App Screenshot",
modifier = Modifier
.height(500.dp)
.fillMaxWidth(),
contentScale = ContentScale.Fit
)
This is an AsyncImage composable that displays an image asynchronously:
model: The image URL from the onboarding object.contentDescription: A text description for the image.modifier: Adjusts the size of the image.contentScale: Scales the image to fit the available space.Text(
text = onboarding?.title.orEmpty(),
fontSize = 19.sp,
fontFamily = latoFamily,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
color = t1Inverse()
)
Displays the title of the onboarding screen using a Text composable with specified attributes including:
Text(
text = onboarding?.subtitle.orEmpty(),
fontSize = 15.sp,
color = t2Inverse(),
fontFamily = latoFamily,
fontWeight = FontWeight.Normal,
lineHeight = 18.sp,
textAlign = TextAlign.Center,
)
Displays the subtitle of the onboarding screen using another Text composable with similar attributes.
NextButton(
title = onboarding?.buttonTitle.orEmpty(),
onClick = onClick,
isEnabled = onboarding?.buttonEnable == true
)
This calls the NextButton composable passing the following parameters:
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
repeat(totalItems) { index ->
Spacer(modifier = Modifier.width(6.dp))
Box(
modifier = Modifier
.size(6.dp)
.background(
color = if (index == currentPos) IND1Dark else IND1Light,
shape = CircleShape
)
)
}
}
Creates a row of page indicators (Box composable) based on the totalItems. The current position currentPos determines the color of the active indicator.
@Composable
fun NextButton(title: String, onClick: () -> Unit, isEnabled: Boolean = true) {
Button(
onClick = onClick,
enabled = isEnabled,
modifier = Modifier
.padding(16.dp)
.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(
containerColor = b2()
)
) {
Text(
text = title,
fontFamily = latoFamily,
fontWeight = FontWeight.Bold,
)
}
}
This is a Composable function named NextButton that displays a button with the following parameters:
title: The text to display on the button.onClick: A lambda function to be called when the button is clicked.isEnabled: A boolean to enable or disable the button.This uses the Button composable to create a clickable button with the following attributes:
The button also utilizes custom colors defined by ButtonDefaults.buttonColors.
Okay, so now the component work is all done. We have to call the above compose function in our activity/fragment.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ShowHorizontalPager() {
val context = LocalContext.current as? Activity
val onboardingViewModel = viewModel(modelClass = OnboardingViewModel::class.java)
val onboardingState = onboardingViewModel.onboardingState.collectAsState()
val coroutineScope = rememberCoroutineScope()
val totalPage = remember { mutableIntStateOf(0) }
totalPage.intValue = onboardingState.value?.screens?.size ?: 0
val pagerState = rememberPagerState(0) { totalPage.intValue }
HorizontalPager(state = pagerState, userScrollEnabled = false, modifier = Modifier.fillMaxSize()) {
onboardingState.value?.screens?.getOrNull(it)?.let { page ->
OnboardingPage(onboarding = page, onClick = {
coroutineScope.launch {
if (pagerState.currentPage == pagerState.pageCount - 1) {
onboardingViewModel.updateShownOnboardingVersions()
Intent(context, MainActivity::class.java).apply {
context?.startActivity(this)
context?.finish()
}
} else {
pagerState.animateScrollToPage(page = pagerState.currentPage + 1)
}
}
}, totalItems = pagerState.pageCount, currentPos = it)
}
}
LaunchedEffect(key1 = Unit) {
onboardingViewModel.fetchOnboarding()
}
}
The ShowHorizontalPager function is a Composable that displays a horizontal pager for onboarding screens.
Activity context.viewModel of type OnboardingViewModel.collectAsState.rememberPagerState.OnboardingPage composable.MainActivity.fetchOnboarding from OnboardingViewModel when the composable is launched.