Sitemap
ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

6 steps to make a “Slide to unlock” button in Jetpack Compose

6 min readApr 8, 2025

--

I recently had the opportunity to work on a custom “Slide to Book” button for one of my projects and since this was my first time implementing a swipe-to-action animation in Jetpack Compose, I thought I’d share the learnings and breakdown the implementation.

This button allows the user to drag a slider thumb horizontally to confirm a booking. Once dragged past a threshold, the button triggers a ride booking action, plays a subtle animation, and displays a loading indicator.

Press enter or click to view image in full size

If you would like to skip this article and just want to see a gif of the end result and go straight for the final code, here’s the link.

Let’s get’s started!

Step 1: Create the Composable

We start by defining the top-level composable for the button. This composable is responsible for the layout and structure of the entire slider: the outer button that holds the text and slider, and the inner slider thumb that the user can drag. Let’s name it SlideToBookButton.

https://gist.github.com/anitaa1990/f0120934810287665e18d097f4557e5f

This composable includes:

  • btnText: The label displayed on the outer track (e.g., “Book Ride ₹199”).
  • btnTextStyle : The typography style for the btnText — allows font weight, size, etc.
  • outerBtnBackgroundColor : The background color for the entire button track.
  • sliderBtnBackgroundColor : The background color for the draggable slider/thumb element.
  • sliderBtnIcon : The icon displayed inside the slider button.
  • onBtnSwipe : The callback invoked when the user successfully completes the swipe.

Step 2: Define the button UI

With our parameters in place, the next step is to define the visual structure of the SlideToBookButton. The layout has two primary components:

  1. The outer button— a full-width container that holds the background and the center aligned button text.
  2. The slider button.thumb — a smaller draggable button layered above the track that users can slide horizontally.
https://gist.github.com/anitaa1990/b969b9273b8594b649f2070d3ba330c5
Press enter or click to view image in full size

Step 3: Add Drag gesture and slide animation

Now that we’ve built the UI for our “Slide to Book” button, let’s start with the animation. We want users to drag the slider thumb from left to right, and once they’ve swiped far enough, we’ll consider it a successful “slide to book” action.

To animate and track the thumb’s position during drag, we’ll need to:

  • Figure out how wide the button is: We use something called Modifier.onSizeChanged to get the actual width of the outer button once it’s displayed. This tells us how far the slider thumb is allowed to move — from the left edge to just before the right edge.
  • Track how far the thumb moves: We use remember { mutableStateOf(… ) } to store the current X-position of the slider thumb in pixels. This allows us to update the thumb’s position reactively as the user drags.
  • Listen for drag gestures: We use Modifier.draggable with rememberDraggableState { delta -> … } to listen for drag gestures in a specified direction (in our case, horizontally). The delta parameter gives us the amount the user’s finger moved since the last update — in pixels, not dp. This means that, every time the user drags their finger left or right, delta tells us how far they moved. We take that delta and add it to our current thumb position, so the thumb follows the finger. If they swipe right, the thumb moves right. If they try to go left again, it moves left — just like dragging a real slider. We also make sure the thumb doesn’t go past the edges. This gives us full control over the drag behavior — not just how far the user can swipe, but when the swipe is “complete”, and even what happens if we want to animate it back later.
  • Finally, we move the thumb visually on the screen: We use Modifier.offset to move a composable by a certain distance on the X (horizontal) or Y (vertical) axis — like nudging it left, right, up, or down. As the user drags their finger, we’re tracking how far they’ve moved using sliderPositionPx (in pixels). We then pass that value to offset — after converting it to dp, since offset expects dp values. This is what makes the slider thumb visually shift across the button, matching the user’s drag. Without offset, even though we’re tracking the finger movement, the thumb would just sit still.

Now let’s update our code:

https://gist.github.com/anitaa1990/92e80882d23ed8c47ca52a29544de50c

This is what we’re achieved so far:

Press enter or click to view image in full size

Step 4: Add text alpha animation

Now that we’ve wired up the drag gesture for the slider button, it’s time to move on to fading out the button text as the slider is dragged. As the user starts sliding: The button label (e.g., “Book Ride ₹199”) gradually fades out. When the slider reaches the end, the text should be completely invisible.

Get Anitaa Murthy’s stories in your inbox

Join Medium for free to get updates from this writer.

To fade out the text label, we’ll need to:

  • measure how far the slider button has been dragged. That gives us a number from 0.0 (not moved at all) to 1.0 (moved all the way to the end). This value is what we call dragProgress.
  • Next, we define and calculate the textAlpha, which controls how transparent the text is. When dragProgress is 0.0 (user hasn’t moved), textAlpha is 1.0 → the text is fully visible. As the user drags and dragProgress increases (like 0.3, 0.5, 0.7…), we decrease the textAlpha to make the text less visible. When dragProgress reaches 1.0 (fully dragged), textAlpha becomes 0.0 → the text is fully invisible. We apply this textAlpha to our Text composable using Modifier.alpha() — so the text fades smoothly while dragging.
https://gist.github.com/anitaa1990/b687344c083275c78ae9f022cc2c2341
Press enter or click to view image in full size
This is what we have so far

Step 5: Add track scale & thumb alpha animation

Once the user slides the button almost to the end, we want two things to happen:

  1. The outer track (button background) should shrink and disappear.
  2. The slider button should fade out completely.

This tells the user that the slide is complete, and the action (like booking the ride) is being processed.

What we need to do:

  • We use a boolean flag sliderComplete that tells us when slide progress has passed a threshold. When dragProgress reaches 80% or more, we set sliderComplete = true.
  • We use animateFloatAsState() and Modifier.graphicsLayer() to smoothly animate the scale and alpha changes.
https://gist.github.com/anitaa1990/bd3d257337317cb71fdfd8ca73188bfb
Press enter or click to view image in full size
And this is what we’ec achieved!

Note: The order of modifiers matters here. We have to ensure that we add the .graphicsLayer above the .background here to ensure that the scaling takes place correctly. If we change the order, i.e. if we add the .background after we add the .graphicsayer, the background is already drawn at full size so the scaling doesn’t affect what’s already been rendered. But if you shrink before, everything is drawn inside the new size — and that’s what you want here!

Step 6: Add the loading indicator animation

Now that we have all the moving parts in place, we simply need to show a loading indicator when the animation is complete. For that, we need to:

  • Define a boolean flag showLoading that tells us when we need to show this loading indicator.
  • We need to update our LaunchedEffect(dragProgress) method to set showLoading = true when sliding is completed.
  • We need to display a CircularProgressIndicator() when showLoading = true.

And this is our full code:

https://gist.github.com/anitaa1990/c2f17982d19d2b5835493596f7755860

And that’s pretty much it!

If you found this useful, feel free to share or reach out with feedback/questions! You can follow more of my Jetpack Compose experiments here:

Happy sliding! 🚜

--

--

Anitaa Murthy
Anitaa Murthy

Written by Anitaa Murthy

Mobile engineer, 10 yrs. I build products end to end: Android, iOS, and the backend behind them. Ex-Automattic. Available for freelance projects.

ProAndroidDev
ProAndroidDev

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.