ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Implementing Parallax Carousel from SwiftUI to Jetpack Compose

This image is generated by Midjourney

As part of my daily routine, I often explore the latest developments on platforms like X and Medium. One morning, while scrolling through X, I stumbled upon a GitHub repository shared by KavSoft that immediately caught my attention. This project, hosted at KavSoft-Tutorials-iOS, showcased a mesmerizing parallax carousel. Its visual appeal and user experience were simply captivating.

Parallax Carousel Slider Using TabView in SwiftUI 2.0 by kenfai

In that moment, I knew I had to roll up my sleeves and recreate this magic in Jetpack Compose for Android. This article serves as a bridge between these two worlds, illustrating how we can transform the SwiftUI Parallax Carousel into its Jetpack Compose equivalent.

Sample project

Our journey begins with the examination of the core components, and for those interested in exploring the detailed code snippets and the complete source code, you can find them all here: ParallaxCarouselCompose.

Let’s commence this transformation by delving into the key components.

TabView → HorizontalPager

To bridge the gap between SwiftUI’s TabView and Jetpack Compose, we turn our attention to HorizontalPager. SwiftUI’s TabView offers a delightful way to swipe through a collection of views seamlessly. In the realm of Android, our transition starts with HorizontalPager.

While it’s important to note that HorizontalPager is still considered experimental, it proves to be a fitting choice for replicating the core functionality of TabView in SwiftUI. With HorizontalPager, we’re able to navigate through a series of images with grace and fluidity, maintaining the desired user experience.

The parallaxOffset calculation is used to determine the position offset of the current page in the carousel. Here's why:

  • pagerState.getOffsetFractionForPage(page): This function retrieves a fractional value representing how far the current page is from its snapped position. It varies between -0.5 (if the page is offset towards the start of the layout) to 0.5 (if the page is offset towards the end of the layout). When the current page is in the snapped position, this value is 0.0. It's a useful indicator of the page's position within the carousel.
  • screenWidth: This is the width of the screen or the display area. Multiplying the fractional offset by the screen width helps scale the offset value to match the screen's dimensions. This step ensures that the parallax effect moves the image proportionally across the screen, making the effect visually pleasing and responsive to the screen size.

GeometryReader → Canvas

Upon examining the SwiftUI code, I noticed the use of GeometryReader, a critical component in achieving the parallax effect. In the realm of Jetpack Compose, we enlist the assistance of Canvas to bring this effect to life.

However, there’s a subtle difference. Unlike SwiftUI, where you can place an image inside GeometryReader with .aspectRatio(contentMode: .fill) to achieve the correct image ratio, Jetpack Compose takes a slightly different approach. Within Canvas, we can't directly use Compose Image. Instead, we employ the drawBitmap function of Canvas to render the images.

To replicate the behavior observed on iOS — an image that spans the full width (equivalent to the screen size) while maintaining the correct height — we delve into some calculation. This involves ensuring that our drawn image maintains the correct aspect ratio.

For those curious, here’s a glimpse of the calculateDrawSize function that handles this calculation.

Now, let’s demystify a crucial aspect: the usage of Canvas translate, parallaxOffset and xOffset. These elements are pivotal in creating the parallax effect we're striving for in Jetpack Compose.

xOffset is defined as an offset value for the parallax effect. It’s calculated as twice the value of cardPadding. This offset determines how much the image is shifted horizontally within the Canvas.

The translate function within the Canvas is used to shift the Canvas horizontally by an amount specified by parallaxOffset. This horizontal translation creates the parallax effect, making the image appear to move horizontally as the user interacts with the carousel.

Result: ParallaxCarousel with Jetpack Compose

Summary

With that, we’ve successfully bridged the gap between SwiftUI and Jetpack Compose, transforming a captivating parallax carousel from one platform to another. As we’ve discovered, while the tools and methods may differ, the end result is equally stunning. Jetpack Compose empowers us to bring our creative visions to life on the Android platform, and this journey is a testament to its flexibility and capabilities.

Before we conclude, it’s worth mentioning that the brilliant Chris Banes has also explored parallax effects in Jetpack Compose. In his insightful article, he demonstrates an alternative approach using alignment. His solution elegantly tackles the parallax effect, and I highly recommend checking out his work for a deeper dive into this topic: Chris Banes - Parallax Effect in Jetpack Compose. It's a testament to the flexibility and capabilities of Jetpack Compose in enabling creative visions on the Android platform.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Imre Kaszab

Senior Android/iOS developer specializing in Kotlin Multiplatform development & AI enthusiast.

No responses yet

Write a response