Utilities
Vertical Parallax Effect
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
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.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.layout
import androidx.compose.ui.unit.dp
import com.composables.uripainter.rememberUriPainter
@Composable
fun VerticalParallaxEffect() {
data class ArticleSummary(val title: String, val coverUrl: String)
val articles = listOf(
ArticleSummary(
title = "The Future of Sustainable Architecture",
coverUrl = "https://images.unsplash.com/photo-1448630360428-65456885c650?q=80&w=1920"
),
ArticleSummary(
title = "The Art of Minimalist Design",
coverUrl = "https://images.unsplash.com/photo-1586023492125-27b2c045efd7?q=80&w=1920"
),
ArticleSummary(
title = "Coffee Culture Around the World",
coverUrl = "https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?q=80&w=1920"
),
ArticleSummary(
title = "The Science of Sleep and Productivity",
coverUrl = "https://images.unsplash.com/photo-1544367567-0f2fcb009e0b?q=80&w=1920"
),
ArticleSummary(
title = "Ocean Conservation: Protecting Marine Life",
coverUrl = "https://images.unsplash.com/photo-1544551763-46a013bb70d5?q=80&w=1920"
),
ArticleSummary(
title = "The Rise of Remote Work Culture",
coverUrl = "https://images.unsplash.com/photo-1521737604893-d14cc237f11d?q=80&w=1920"
),
ArticleSummary(
title = "Ancient Forests: Nature's Timeless Beauty",
coverUrl = "https://images.unsplash.com/photo-1441974231531-c6227db76b6e?q=80&w=1920"
),
ArticleSummary(
title = "Urban Gardening: Green Cities Initiative",
coverUrl = "https://images.unsplash.com/photo-1416879595882-3373a0480b5b?q=80&w=1920"
),
ArticleSummary(
title = "The Art of Japanese Tea Ceremony",
coverUrl = "https://images.unsplash.com/photo-1544787219-7f47ccb76574?q=80&w=1920"
),
ArticleSummary(
title = "Northern Lights: Arctic Wonder",
coverUrl = "https://images.unsplash.com/photo-1531366936337-7c912a4589a7?q=80&w=1920"
),
ArticleSummary(
title = "Desert Landscapes: Beauty in Aridity",
coverUrl = "https://images.unsplash.com/photo-1509316785289-025f5b846b35?q=80&w=1920"
),
)
fun Modifier.verticalParallax(listState: LazyListState, index: Int, rate: Float = 2f) = this.then(
Modifier.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
val itemOffset = listState.layoutInfo.visibleItemsInfo.find { it.index == index }?.offset ?: 0
val offsetY = itemOffset / rate
layout(placeable.width, placeable.height) {
placeable.place(0, offsetY.toInt())
}
}
)
val state = rememberLazyListState()
LazyColumn(
state = state,
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(24.dp),
contentPadding = PaddingValues(24.dp),
) {
articles.forEachIndexed { i, article ->
item {
Card(Modifier.height(280.dp)) {
Box(Modifier.fillMaxSize()) {
Image(
painter = rememberUriPainter(article.coverUrl),
contentDescription = article.title,
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(unbounded = true)
.verticalParallax(state, rate = 5f, index = i)
)
Box(
Modifier
.align(Alignment.BottomStart)
.fillMaxWidth()
.background(
Brush.verticalGradient(
colors = listOf(
Color.Transparent,
Color.Black.copy(alpha = 0.2f),
Color.Black.copy(alpha = 0.4f)
)
)
)
.padding(16.dp)
) {
Text(article.title, color = Color.White)
}
}
}
}
}
}
}
Horizontal Pager Indicator
Explore other Jetpack Compose Blocks

Accordions
3 blocks

Autocomplete
4 blocks
Avatars
3 blocks

Bottom sheets
4 blocks

Button Groups
4 blocks

Buttons
7 blocks

Cards
13 blocks

Checkboxes
4 blocks

Chips
4 blocks

Date Pickers
2 blocks

Dialogs
5 blocks

Dropdown Menus
4 blocks

Expandable Lists
3 blocks

Feeds
5 blocks

Form Inputs
6 blocks

Forms
4 blocks

Grids
9 blocks

Horizontal Lists
4 blocks

Lists
6 blocks

Modal Bottom sheets
6 blocks

Music Playback
4 blocks

Radio Groups
3 blocks

Responsive Layouts
5 blocks

Search Bars
2 blocks

Social Share
3 blocks

Tables
8 blocks

Tabs
7 blocks

Text Fields
6 blocks

Toggles
3 blocks

Utilities
2 blocks

Accept Privacy
1 blocks

Chat
1 blocks

Forgot Password
1 blocks

Onboarding
3 blocks

Profile Details
5 blocks

Request Permission
1 blocks

Search
1 blocks

Settings
2 blocks

Sign In
1 blocks

Sign Up
1 blocks

Checkout Forms
2 blocks

Product Details
2 blocks

Product Filters
3 blocks

Product Lists
3 blocks

Product Reviews
2 blocks

Shopping Cart
4 blocks