Swipe-for-action cards like Gmail using Jetpack Compose

In this short tutorial, I will show how you can create cards in Jetpack Compose which can be swiped either left or right to perform any action. This is similar to swiping an email in a Gmail inbox.

SwipeableActionCard in the sample app

Apart from animating the content card back, you can also remove it from the LazyColumnor perform any other operation as required.

You can import my library and use SwipeableActionCard out of the box. It has enough APIs to customise the behaviour you would use most of the time.

// In your project level build.gradle fileallprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
// In your module build.gradle filedependencies {
implementation 'com.github.Harsh2098:SwipeableActionCard:1.0.0'
}

Nevertheless, you can continue reading to know how we can implement such behaviour.

  1. Very basic knowledge of Jetpack Compose like managing states.
  2. Kotlin coroutines.

Let us briefly go through the requirements before we dive deep into the steps for the actual implementation:

  1. Able to handle swipe gesture
    → Compose provides swipeable modifier which lets you drag elements. We can specify anchors but it still needs to be configured for our use case. It is important to note that this modifier does not move the element, it only detects the gesture.
  2. Able to resize the action card according to the main content card
    → Constraint layout to the rescue! We can set up constraints on the action card to match the main content card. Note: We need to grab constraintlayout-compose dependency. Check out build.gradle in the sample repository for more details.
  3. Performant to prevent UI janking
    → We will either be showing left action card or right action card at a time so we can have a single Surface for them. Also, we need to make sure that animateTo is called within a coroutine.

Let us look at 3 main steps to implement a swipeable action card:

Step1 — Defining the API

Let us first define the parameters for our SwipeableActionCard composable.
We need 3 composables for main card, left action card and right action card. We also take in 2 lambda functions which can be triggered whenever the state updates.

User will not see left and right action cards at the same time. As we don’t need to display both action cards at the same time we can have just a single surface for our action card.

Step 2— Declaring states and anchors

Specify constraints on the surfaces so that the width and height of the action card match the main card. Let us also grab screen width from LocalConfiguration, specify anchors to animate the main card towards and declare mutable states to keep track of the offset.

The main card’s constraint can be as per your requirement but the action card’s top and bottom are constrained to the main card’s top & bottom. It is important to specify height = Dimension.fillToConstraints otherwise, it will wrap content and it won’t take up the entire space available.

Note: We have created an enum class to represent the different states.

private enum class SwipeCardState {
DEFAULT,
LEFT,
RIGHT
}

Step 3 — Calling swipe functions and animating back via a coroutine

You can view the full SwipeableActionCard implementation here.

SG Bus Buddy uses this library to add/delete buses from favourites.

Android Developer@Shopee