Expandable Card with Animation in Jetpack Compose

Introduction

The concept of the expandable card is widely recognized within the realm of Android applications. Expandable cards allow users to interact with content that can be expanded or collapsed, providing a more organized and user-friendly interface. In this article, we will dive into the concept of expandable cards and explore how to create them using Jetpack Compose.

Here we will make a custom composable with some parameters that will allow us to customize our composable function. we can directly use this function in any project. Here is the function explained in detail-

Step 1. Defining the Composable Function

The expandable card is encapsulated within a composable function named ExpandableCard. This function is annotated @Composable, indicating that it defines a UI component that can be used within Jetpack Compose's compositional structure.

fun ExpandableCard(
    title: String,
    titleFontSize: TextUnit = MaterialTheme.typography.titleLarge.fontSize,
    titleFontWeight: FontWeight = FontWeight.Bold,
    description: String,
    descriptionFontSize: TextUnit = MaterialTheme.typography.titleSmall.fontSize,
    descriptionFontWeight: FontWeight = FontWeight.Normal,
    descriptionMaxLines: Int = 4,
    shape: Shape = sharpShapes.medium,
    padding: Dp = 12.dp
) {
       // Card components to be 
}

Step 2. Managing Expanded State

The core functionality of the expandable card revolves around its ability to expand and collapse its content. This behavior is managed using a mutable state variable named expandedState. When the card is clicked, this state toggles between true (expanded) and false (collapsed), thereby controlling the visibility of the description text.

    var expandedState by remember { mutableStateOf(false) }

Step 3. Animating the Arrow Rotation

The expand/collapse arrow icon's rotation is animated using the animateFloatAsState function. This animation smoothly rotates the arrow from 0 degrees (collapsed state) to 180 degrees (expanded state) and vice versa. The rotationState holds the current rotation angle based on the expandedState.

    val rotationState by animateFloatAsState(
        targetValue = if (expandedState) 180f else 0f
    )

Step 4. Creating the Card Container

The Card composable is utilized to create the visual representation of the expandable card. It provides a styled container with elevation, background, and rounded corners. The Card takes several modifiers, including fillMaxWidth() to stretch across the available width and animateContentSize() to enable smooth content-size animations.

    Card(
        modifier = Modifier
            .fillMaxWidth()
            .animateContentSize(
                animationSpec = tween(
                    durationMillis = 300,
                    easing = LinearOutSlowInEasing
                )
            ),
        shape = shape,
        onClick = {
            expandedState = !expandedState
        }
    ) {
                // card content

    }

Step 5. Layout and Content Composition

Inside the Card, a Column composable is used to arrange the card's content vertically. Within the column, a Row composable arranges the title and the expand/collapse arrow icon horizontally. The Text composable displays the title and description, while the IconButton composable holds the arrow icon. The arrow's rotation is controlled by the rotationState, and the description text's visibility depends on the expandedState.

        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(padding)
        ) {
            Row(
                verticalAlignment = Alignment.CenterVertically
            ) {
                Text(
                    modifier = Modifier
                        .weight(6f),
                    text = title,
                    fontSize = titleFontSize,
                    fontWeight = titleFontWeight,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis
                )
                IconButton(
                    modifier = Modifier
                        .weight(1f)
                        .alpha(0.2f)
                        .rotate(rotationState),
                    onClick = {
                        expandedState = !expandedState
                    }) {
                    Icon(
                        imageVector = Icons.Default.ArrowDropDown,
                        contentDescription = "Drop-Down Arrow"
                    )
                }
            }
            if (expandedState) {
                Text(
                    text = description,
                    fontSize = descriptionFontSize,
                    fontWeight = descriptionFontWeight,
                    maxLines = descriptionMaxLines,
                    overflow = TextOverflow.Ellipsis
                )
            }
        }

Output

Summary

In this article, we explored the concept of expandable cards in Jetpack Compose, which allows users to interact with content that can be expanded or collapsed. We dissected a code snippet that showcases the creation of an expandable card using Compose's declarative approach. The code demonstrated the use of various Compose concepts such as state management, animations, modifiers, and custom composable functions to achieve the desired behavior. By leveraging expandable cards, developers can enhance the user experience of their Android applications, providing users with a seamless way to access additional information while keeping the interface clean and organized.

Hope this has been a helpful guide for you; it will be helpful for me if you write your genuine comment about this article. Thank you!


Similar Articles