Ice Cream App COMPOSE UI UX
Ice Cream App android COMPOSE UI UX, where you can display your ice cream collection. In the application, you will find many screens: Splash Screen, Categories Screen, Details Screen, and Custom Dialog Screen.
Onboarding is a virtual unboxing experience that helps users get started with an app.
OnBoarding.kt
package io.material.compose.ui.design
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.spring
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.KeyboardArrowLeft
import androidx.compose.material.icons.outlined.KeyboardArrowRight
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.rememberPagerState
import io.material.compose.model.OnBoardingItems
import kotlinx.coroutines.launch
@ExperimentalPagerApi
@Preview
@Composable
fun OnBoarding() {
val items = OnBoardingItems.getData()
val scope = rememberCoroutineScope()
val pageState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
TopSection(
onBackClick = {
if (pageState.currentPage + 1 > 1) scope.launch {
pageState.scrollToPage(pageState.currentPage - 1)
}
},
onSkipClick = {
if (pageState.currentPage + 1 < items.size) scope.launch {
pageState.scrollToPage(items.size - 1)
}
}
)
HorizontalPager(
count = items.size,
state = pageState,
modifier = Modifier
.fillMaxHeight(0.9f)
.fillMaxWidth()
) { page ->
OnBoardingItem(items = items[page])
}
BottomSection(size = items.size, index = pageState.currentPage) {
if (pageState.currentPage + 1 < items.size) scope.launch {
pageState.scrollToPage(pageState.currentPage + 1)
}
}
}
}
@ExperimentalPagerApi
@Composable
fun TopSection(onBackClick: () -> Unit = {}, onSkipClick: () -> Unit = {}) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
) {
// Back button
IconButton(onClick = onBackClick, modifier = Modifier.align(Alignment.CenterStart)) {
Icon(imageVector = Icons.Outlined.KeyboardArrowLeft, contentDescription = null)
}
// Skip Button
TextButton(
onClick = onSkipClick,
modifier = Modifier.align(Alignment.CenterEnd),
contentPadding = PaddingValues(0.dp)
) {
Text(text = "Skip", color = MaterialTheme.colors.onBackground)
}
}
}
@Composable
fun BottomSection(size: Int, index: Int, onButtonClick: () -> Unit = {}) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
) {
// Indicators
Indicators(size, index)
// FAB Next
FloatingActionButton(
onClick = onButtonClick,
backgroundColor = MaterialTheme.colors.primary,
contentColor = MaterialTheme.colors.onPrimary,
modifier = Modifier.align(Alignment.CenterEnd)
) {
Icon(imageVector = Icons.Outlined.KeyboardArrowRight, contentDescription = "Next")
}
}
}
@Composable
fun BoxScope.Indicators(size: Int, index: Int) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier.align(Alignment.CenterStart)
) {
repeat(size) {
Indicator(isSelected = it == index)
}
}
}
@Composable
fun Indicator(isSelected: Boolean) {
val width = animateDpAsState(
targetValue = if (isSelected) 25.dp else 10.dp,
animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy)
)
Box(
modifier = Modifier
.height(10.dp)
.width(width.value)
.clip(CircleShape)
.background(
color = if (isSelected) MaterialTheme.colors.primary else Color(0XFFF8E2E7)
)
) {
}
}
@Composable
fun OnBoardingItem(items: OnBoardingItems) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxSize()
) {
Image(painter = painterResource(id = items.image), contentDescription = "Image1")
Text(
text = stringResource(id = items.title),
style = androidx.compose.material3.MaterialTheme.typography.labelLarge,
fontSize = 24.sp,
color = MaterialTheme.colors.onBackground,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center
)
Text(
text = stringResource(id = items.desc),
style = androidx.compose.material3.MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colors.onBackground,
fontWeight = FontWeight.Light,
textAlign = TextAlign.Center,
modifier = Modifier.padding(10.dp)
)
}
}
OnBoarding.kt
package io.material.compose
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.google.accompanist.pager.ExperimentalPagerApi
import io.material.compose.ui.design.OnBoarding
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPagerApi::class)
@Composable
fun OnboardDemo() {
OnBoarding()
}
@ExperimentalPagerApi
@Preview(showBackground = true)
@Composable
fun PreviewFunction(){
Surface(modifier = Modifier.fillMaxSize()) {
OnBoarding()
}
}
..