How to do the parallax scroll with jetpack compose
In this tutorial you will learn how to do the parallax effect in jetpack compose on an image in a scroll view. You will learn how to use the Column, scroll it using the verticalScroll, how to use graphicsLayer to apply the parallax effect on the image. You will also learn how to load an image asynchronously and how to place the views inside the scrollview using the Column view and jetpack compose view modifiers.
Define the view
Here is the basic view we will use. It's composed by a Column that scrolls vertically using the verticalScroll modifier, an image and a text.
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
) {
AsyncImage(
model = "https://images.unsplash.com/photo-1648737922331-0b5e338215bc?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=300&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY0OTg2NTgyNA&ixlib=rb-1.2.1&q=80&w=720",
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
)
Column(modifier = Modifier
.background(Color.White)
.fillMaxWidth()
.padding(10.dp)) {
Text(
text = stringResource(R.string.loremlipsum),
fontSize = 15.sp,
lineHeight = 30.sp
)
}
}
The image is loaded using the coil AsyncImage component. The Column modifier allows to put views with a vertical order. The fillMaxSize allows to extend the view to the maximum available size.
Parallax Effect with jetpack compose
In order to do the parallax effect with jetpack compose, you will need to use the graphicsLayer modifier. Here are all the transitions that can be applied to the graphicsLayer modifier:
alpha = alpha,
translationX = translationX,
translationY = translationY,
shadowElevation = shadowElevation,
scaleX = scaleX,
scaleY = scaleY,
rotationX = rotationX,
rotationY = rotationY,
rotationZ = rotationZ,
cameraDistance = cameraDistance,
transformOrigin = TransformOrigin(originX, originY),
shape = roundedDegree,
clip = true,
renderEffect = BlurEffect(blur, blur)
In our example, we will use the translationY modifier to move the image down, while scrolling up, and doind the parallax effect.
.graphicsLayer {
translationY = scrollState.value * 0.2f
}
You can also apply the blur effect while scrolling, or any other effect you wish:
.graphicsLayer {
translationY = scrollState.value * 0.2f
if(scrollState.value > 0){
renderEffect = BlurEffect( scrollState.value * 0.1f, scrollState.value * 0.1f)
}
}
Final Code
@Composable
fun View() {
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
) {
AsyncImage(
model = "https://images.unsplash.com/photo-1648737922331-0b5e338215bc?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=300&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY0OTg2NTgyNA&ixlib=rb-1.2.1&q=80&w=720",
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.fillMaxWidth()
.height(400.dp)
.graphicsLayer {
translationY = scrollState.value * 0.2f
if(scrollState.value > 0){
renderEffect = BlurEffect( scrollState.value * 0.1f, scrollState.value * 0.1f)
}
}
)
Column(modifier = Modifier
.background(Color.White)
.fillMaxWidth()
.padding(10.dp)) {
Text(
text = stringResource(R.string.loremlipsum),
fontSize = 15.sp,
lineHeight = 30.sp
)
}
}
}