How to Create Expandable Card in Android Jetpack Compose
Building dynamic user interfaces in Android has never been easier with the introduction of Jetpack Compose. This toolkit takes a modern, declarative approach to UI, making UI development more intuitive and efficient.
In this blog post, we will focus on creating an expandable card, a popular UI element often used to minimize information overload while still providing users with the option to access more details if needed.
What makes this card special is its expandable feature: upon user interaction, the card smoothly transitions between collapsed and expanded states. This is achieved using Jetpack Compose’s animateContentSize() modifier.
Let’s dive into the code:
@Composable
fun CardExample() {
var expanded by remember { mutableStateOf(false) }
Column {
Card(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
.animateContentSize(), // This is where the magic happens!
onClick = { expanded = !expanded }
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(text = "Tap to expand")
// This content will be shown when the card is expanded
if (expanded) {
Text(
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vehicula, urna vel tempus congue, quam erat lacinia ipsum, id cursus tellus diam et lacus. Fusce condimentum ultricies purus, et aliquam orci tristique in. Suspendisse euismod accumsan massa, a hendrerit velit vehicula ac. Nulla facilisi.",
modifier = Modifier.padding(top = 16.dp)
)
}
}
}
}
}
The expanded state, which is remembered across recompositions, controls the visibility of the extra content within the card. The state toggles between true and false when the card is clicked.
Now, the most critical piece is the .animateContentSize() modifier. It enables the smooth transition of the card’s size when the expanded state changes. The additional content is gradually revealed, providing a visually pleasing effect and enhancing user experience.
Following is the output.
Following is the complete code for reference.
package com.example.example
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.example.ui.theme.ExampleTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
ExampleTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
CardExample()
}
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CardExample() {
var expanded by remember { mutableStateOf(false) }
Column {
Card(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
.animateContentSize(), // This is where the magic happens!
onClick = { expanded = !expanded }
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
Text(text = "Tap to expand")
// This content will be shown when the card is expanded
if (expanded) {
Text(
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vehicula, urna vel tempus congue, quam erat lacinia ipsum, id cursus tellus diam et lacus. Fusce condimentum ultricies purus, et aliquam orci tristique in. Suspendisse euismod accumsan massa, a hendrerit velit vehicula ac. Nulla facilisi.",
modifier = Modifier.padding(top = 16.dp)
)
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun ExamplePreview() {
ExampleTheme {
CardExample()
}
}
With just a few lines of code, we were able to create an expandable card with a smooth animation. This showcases the power and ease of Jetpack Compose, simplifying the development of complex UI components and encouraging more interactive user interfaces.