feat: Optimize onboarding animations and improve page swiping performance

This commit is contained in:
k1ngsterr1
2026-01-15 22:40:24 +05:00
parent e7e6d23631
commit 80f5e436ee

View File

@@ -247,15 +247,17 @@ fun OnboardingScreen(
modifier = Modifier
.fillMaxWidth()
.height(150.dp),
// Pre-load adjacent pages for smooth swiping
beyondBoundsPageCount = 2,
flingBehavior = PagerDefaults.flingBehavior(
state = pagerState,
lowVelocityAnimationSpec = tween(
durationMillis = 300,
durationMillis = 250,
easing = FastOutSlowInEasing
),
snapAnimationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessLow
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessMedium
)
)
) { page ->
@@ -372,42 +374,20 @@ fun AnimatedRosettaLogo(
bookComposition: Any?,
modifier: Modifier = Modifier
) {
val currentPage = pagerState.currentPage
val pageOffset = pagerState.currentPageOffsetFraction
// Animate scale and alpha based on swipe
val scale by animateFloatAsState(
targetValue = 1f - (pageOffset.absoluteValue * 0.08f),
animationSpec = tween(400, easing = FastOutSlowInEasing),
label = "scale"
)
val alpha by animateFloatAsState(
targetValue = 1f - (pageOffset.absoluteValue * 0.3f),
animationSpec = tween(400, easing = FastOutSlowInEasing),
label = "alpha"
)
// Use derivedStateOf for optimized reads
val currentPage by remember { derivedStateOf { pagerState.currentPage } }
Box(
modifier = modifier
.graphicsLayer {
// Enable hardware acceleration
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
},
modifier = modifier,
contentAlignment = Alignment.Center
) {
// Pre-render all animations to avoid lag
Box(
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
// Hardware layer for better performance
renderEffect = null
},
contentAlignment = Alignment.Center
// Rosetta icon (page 0) with pulse animation like splash screen
androidx.compose.animation.AnimatedVisibility(
visible = currentPage == 0,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(200))
) {
// Rosetta icon (page 0) with pulse animation like splash screen
if (currentPage == 0) {
Box(contentAlignment = Alignment.Center) {
val pulseScale by rememberInfiniteTransition(label = "pulse").animateFloat(
initialValue = 1f,
targetValue = 1.1f,
@@ -418,7 +398,7 @@ fun AnimatedRosettaLogo(
label = "pulseScale"
)
// Glow effect behind logo - same style as splash screen
// Glow effect behind logo
Box(
modifier = Modifier
.size(180.dp)
@@ -429,7 +409,7 @@ fun AnimatedRosettaLogo(
)
)
// Main logo - circular like splash screen
// Main logo
Image(
painter = painterResource(id = R.drawable.rosetta_icon),
contentDescription = "Rosetta Logo",
@@ -438,111 +418,97 @@ fun AnimatedRosettaLogo(
.clip(CircleShape)
)
}
// Fast page - idea animation (page 1)
// Load adjacent pages for smooth swiping
val shouldLoadIdea = currentPage in 0..2
if (shouldLoadIdea) {
ideaComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = currentPage == 1,
speed = 1.2f // Faster for smoother perception
)
if (currentPage == 1) {
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
// Hardware acceleration for smooth rendering
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
},
maintainOriginalImageBounds = true
)
}
}
}
// Idea animation (page 1)
androidx.compose.animation.AnimatedVisibility(
visible = currentPage == 1,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(200))
) {
ideaComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = true,
speed = 1.5f
)
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier.fillMaxSize(),
maintainOriginalImageBounds = true
)
}
// Free page - money animation (page 2)
val shouldLoadMoney = currentPage in 1..3
if (shouldLoadMoney) {
moneyComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = currentPage == 2,
speed = 1.2f
)
if (currentPage == 2) {
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
},
maintainOriginalImageBounds = true
)
}
}
}
// Money animation (page 2)
androidx.compose.animation.AnimatedVisibility(
visible = currentPage == 2,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(200))
) {
moneyComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = true,
speed = 1.5f
)
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier.fillMaxSize(),
maintainOriginalImageBounds = true
)
}
// Secure page - lock animation (page 3)
val shouldLoadLock = currentPage in 2..4
if (shouldLoadLock) {
lockComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = currentPage == 3,
speed = 1.2f
)
if (currentPage == 3) {
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
},
maintainOriginalImageBounds = true
)
}
}
}
// Lock animation (page 3)
androidx.compose.animation.AnimatedVisibility(
visible = currentPage == 3,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(200))
) {
lockComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = true,
speed = 1.5f
)
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier.fillMaxSize(),
maintainOriginalImageBounds = true
)
}
// Private page - book animation (page 4)
val shouldLoadBook = currentPage in 3..4
if (shouldLoadBook) {
bookComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = currentPage == 4,
speed = 1.2f
)
if (currentPage == 4) {
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier
.fillMaxSize()
.graphicsLayer {
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
},
maintainOriginalImageBounds = true
)
}
}
}
// Book animation (page 4)
androidx.compose.animation.AnimatedVisibility(
visible = currentPage == 4,
enter = fadeIn(animationSpec = tween(200)),
exit = fadeOut(animationSpec = tween(200))
) {
bookComposition?.let { comp ->
val lottieComp = comp as? com.airbnb.lottie.LottieComposition
val progress by animateLottieCompositionAsState(
composition = lottieComp,
iterations = 1,
isPlaying = true,
speed = 1.5f
)
LottieAnimation(
composition = lottieComp,
progress = { progress },
modifier = Modifier.fillMaxSize(),
maintainOriginalImageBounds = true
)
}
}
}