Thanks to Jetpack Compose, implementing gestures is easier than ever. The only thing we need to assign an action to a gesture, is a Composable and a lambda. 

We are going to see how to add this functionality with code samples for a Composable that is representing a vertical clock.

How to add vertical gestures

To add gestures, we are going to need modifiers. In this case, to recognize a vertical swipe, up or down, the scrollable modifier is needed, which takes the orientation of the gesture and a state.

This state is provided by rememberScrollableState, and its delta argument is what is going to tell us if the gesture is representing a scroll down or a scroll up. If the delta argument is negative, then the user is scrolling up, and you can imagine what happens if the delta is positive.

This makes sense as the UI is defined by two coordinates axis that have the (0,0) point in the upper left corner.

Here you have a sample code with the scrollable modifier implemented.

.scrollable(
    orientation = Orientation.Vertical,
    state = rememberScrollableState { delta ->
      when {
        delta < 0 -> onScrollUp(delta)
        delta > 0 -> onScrollDown(delta)
        else -> {}
      }
      delta
    }
)
Kotlin

How to add horizontal gestures

The same principle is applied here. We use the scrollable modifier, but with the orientation specified as horizontal. 

Following what we said before about where the (0,0) point is in the coordinates, if the delta is positive, a swipe right is being done, and if it is negative, we are going to register a swipe left. 

If we want to apply a horizontal and a vertical gesture to the same Composable, then we would need to add to scrollable modifiers to it.

Here there is an example of the horizontal gesture.

.scrollable(
    orientation = Orientation.Horizontal,
    state = rememberScrollableState { delta ->
      when {
        delta < 0 -> onSwipeLeft(delta)
        delta > 0 -> onSwipeRight(delta)
        else -> {}
      }
      delta
    }
 )
Kotlin

How to add tap gestures

If we want to manage double taps or a long press, we have to use another modifier, in this case, the one called pointerInput

Here with the detectTapGestures function we can specify an action for each of the different kinds of taps, with a lambda, as you can see in the following example.

.pointerInput(Unit) {
    detectTapGestures(
      onPress = {},
      onDoubleTap = {},
      onLongPress = { onLongPress() },
      onTap = { onClick() }
    )
 }
Kotlin

With all that, we could have the following Composable, which represents a timer that can be controlled with that all those taps and gestures.

fun VerticalClock(
  modifier: Modifier = Modifier,
  clock: Clock,
  onClick: () -> Unit,
  onLongPress: () -> Unit,
  onScrollDown: (Float) -> Unit,
  onScrollUp: (Float) -> Unit,
  onHorizontalScroll: (Float) -> Unit
) {
 Column(
  verticalArrangement = Arrangement.Center,
  horizontalAlignment = Alignment.CenterHorizontally,
  modifier = modifier
   .fillMaxWidth()
   .pointerInput(Unit) {
    detectTapGestures(
      onPress = {},
      onDoubleTap = {},
      onLongPress = { onLongPress() },
      onTap = { onClick() }
    )
   }
   .background(MaterialTheme.colorScheme.background)
   .scrollable(
    orientation = Orientation.Vertical,
    state = rememberScrollableState { delta ->
      when {
        delta < 0 -> onScrollUp(delta)
        delta > 0 -> onScrollDown(delta)
        else -> {}
      }
      delta
    }
   )
   .scrollable(
    orientation = Orientation.Horizontal,
    state = rememberScrollableState { delta ->
      when {
         delta < 0 -> onSwipeLeft(delta)
         delta > 0 -> onSwipeRight(delta)
         else -> {}
      }
      delta
    }
   )
) {
  with(clock) {
    ClockPair(
      verticalAlignment = Alignment.Bottom,
      firstDigit = firstDigit,
      secondDigit = secondDigit
    )
    ClockPair(
      verticalAlignment = Alignment.Top,
      firstDigit = thirdDigit,
      secondDigit = fourthDigit
    )
  }
 }
}
Kotlin

Featured image by Liana Mikah on Unsplash


If you want to read more content like this and support me, don’t forget to check the rest of the bolg or subscribe here to get an email every time I publish new content.

Categorized in: