Introduction
Jetpack Compose, the modern toolkit for building native UI in Android applications, offers a flexible and powerful way to create smooth and interactive user interfaces with minimal code. One of the most engaging aspects of user interaction in apps is swiping gestures, which can enhance the overall experience by allowing users to navigate content or perform actions fluidly. In this article, we'll dive into an example that demonstrates how to create a swiping UI component using Jetpack Compose, while also incorporating animated transitions to add a bit of flair.
This guide will walk you through a practical implementation of a swiping feature in Jetpack Compose, where users can swipe a colorful box horizontally. Along the way, we'll explore how to handle state, manage animations, and use gestures in Compose to achieve a smooth and interactive design. Let’s break down how the example code works, step by step.
Setting Up the Main Content
At the core of this example is the MainContent()
function, which serves as the main composable that renders the user interface. The design centers around a swiping component where a colorful box can be moved horizontally across the screen. To achieve this, Jetpack Compose's swipeable
modifier is employed. This modifier allows the box to respond to swipe gestures and change its position based on user input.
A key element here is the swipeAbleState
, which uses rememberSwipeableState()
to track the current position of the swipe. The swipeable state works in conjunction with anchors to define where the swipeable box can snap to. In this example, there are two anchor points: one at the starting position (0) and another at the end position, defined based on the size of the box in pixels. The use of anchors ensures that the box either snaps back to its original position or moves fully to the other side when released.
Implementing Animated Color Changes
One of the visually appealing aspects of this swiping example is the animated color change of the box. To accomplish this, the code uses animateColorAsState()
, which smoothly transitions the background color of the swipable box whenever the color state changes. The color transition is controlled with a tween()
function that specifies a duration of 2,000 milliseconds, creating a gradual and pleasing animation effect.
To change the color dynamically, two IconButton
components are included in the UI. These buttons allow users to set the background color of the swipable box to either blue or red. Clicking on one of these buttons updates the state variable bgColor
, which triggers the animateColorAsState()
function to animate the color change. This integration of gestures and animations showcases the flexibility and power of Jetpack Compose for creating interactive UIs.
Utilizing Swipeable Modifiers and Offsets
The Box
composable used for the swiping component includes several modifiers that control its layout and behavior. The swipeable
modifier is configured with parameters like anchors
, thresholds
, and orientation
. The FractionalThreshold
parameter ensures that the swipe gesture must cover at least 30% of the total distance before it transitions to the next anchor point. This helps create a more intuitive user experience, where the swipable box doesn't move too easily or unintentionally.
In addition, the offset
modifier uses the swipeable state’s offset value to position the box dynamically as the user swipes. This offset value is continuously updated based on the swipe gestures, ensuring smooth motion as the box slides back and forth. The IntOffset
is used to convert the floating-point offset into integer coordinates, which are then applied to adjust the box's horizontal position on the screen.
Composing a Flexible Layout
The layout of the entire swiping interface is organized using a Column
, ensuring that all elements are centered both vertically and horizontally on the screen. This layout structure is wrapped in a Box
with rounded corners and padding, providing a clean and visually appealing design. The background color of the entire screen is set to a neutral tone to make the colored swipable box stand out.
The swipable box itself is defined within another Box
that fills most of the screen’s width and maintains a fixed height. This design approach keeps the focus on the interactive element, making it the centerpiece of the user interface. By combining layout composables like Box
and Column
with gesture handling, the code efficiently manages both content organization and interactivity.
Summary
This Jetpack Compose swiping example demonstrates how to leverage the toolkit's powerful capabilities to build engaging and responsive UI components. By integrating gesture handling, animations, and state management, you can create interactive elements that enhance the user experience. The use of swipeable
modifiers, state variables, and animated transitions allows for a seamless blend of functionality and aesthetics.
Whether you're looking to implement a swiping feature for navigation, action triggers, or purely visual effects, this example serves as a solid foundation. Jetpack Compose’s concise and intuitive API makes it easier than ever to build dynamic interfaces with minimal effort, paving the way for more creative and interactive Android applications.
package com.cfsuman.jetpackcompose
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ColorLens
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import kotlin.math.roundToInt
class MainActivity : AppCompatActivity() {
@ExperimentalMaterialApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainContent()
}
}
@ExperimentalMaterialApi
@Composable
fun MainContent(){
var bgColor:Color by remember {
mutableStateOf(Color(0xFF88540B))
}
val color = animateColorAsState(
targetValue = bgColor,
animationSpec = tween(
durationMillis = 2000
)
)
val squareSize = 150.dp
val swipeAbleState = rememberSwipeableState(0)
val sizePx = with(LocalDensity.current) { squareSize.toPx() }
val anchors = mapOf(0f to 0, sizePx to 1)
Column(
modifier = Modifier
.background(Color(0xFFEDEAE0))
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(16.dp))
.background(Color(0xFFBFAFB2))
.padding(8.dp)
.swipeable(
state = swipeAbleState,
anchors = anchors,
thresholds = { _, _ ->
FractionalThreshold(0.3f)
},
orientation = Orientation.Horizontal
)
) {
Column(
modifier = Modifier.padding(16.dp)
) {
IconButton(onClick = {
bgColor = Color(0xFF2A52BE)
}) {
Icon(
Icons.Filled.ColorLens,
contentDescription = "Localized description",
tint = Color(0xFF2A52BE)
)
}
IconButton(onClick = {
bgColor = Color(0xFFE30022)
}) {
Icon(
Icons.Filled.ColorLens,
contentDescription = "Localized description",
tint = Color(0xFFE30022)
)
}
}
Box(
Modifier
.offset {
IntOffset(
swipeAbleState.offset.value.roundToInt(),
0
)
}
.clip(RoundedCornerShape(16.dp))
.fillMaxWidth(0.95F)
.height(150.dp)
.background(color.value)
)
}
}
}
@Preview
@Composable
fun ComposablePreview(){
//MainContent()
}
}
- jetpack compose - Navigation drawer example
- jetpack compose - Cut corner shape example
- jetpack compose - Image from drawable
- jetpack compose - Image clickable
- jetpack compose - Image border
- jetpack compose - Image shape
- jetpack compose - Image tint
- jetpack compose - Image from assets folder
- jetpack compose - How to use LazyColumn
- jetpack compose - Accessing string resources
- jetpack compose - String resource positional formatting
- jetpack compose - Dragging
- jetpack compose - Multiple draggable objects
- jetpack compose - Panning zooming rotating
- jetpack compose - Weight modifier