Skip to main content

Create Dynamic Visibility Effects with AnimatedVisibility in Jetpack Compose

Jetpack Compose is transforming the Android development landscape with its declarative UI toolkit, offering simplicity and flexibility. One of its standout features is AnimatedVisibility, which enables developers to create smooth and dynamic visibility transitions for their composables. This article dives deep into AnimatedVisibility, exploring its advanced use cases, best practices, and optimization techniques.

What Is AnimatedVisibility?

AnimatedVisibility is part of Jetpack Compose's animation library, providing an intuitive way to animate the appearance and disappearance of UI elements. It handles complex visibility transitions with minimal boilerplate code.

Key Features of AnimatedVisibility

  • Declarative API: Simplifies code with a clear, expressive API.

  • Built-in Animation Support: Offers default fade-in and fade-out effects.

  • Customization: Allows developers to define custom enter and exit animations.

  • State-Based Transitions: Seamlessly integrates with Compose's state management.

Basic Usage

Here is a simple example of AnimatedVisibility in action:

@Composable
fun BasicAnimatedVisibilityExample() {
    var isVisible by remember { mutableStateOf(true) }

    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Button(onClick = { isVisible = !isVisible }) {
            Text("Toggle Visibility")
        }

        AnimatedVisibility(visible = isVisible) {
            Text("Hello, Jetpack Compose!", style = MaterialTheme.typography.h5)
        }
    }
}

This example toggles the visibility of a text composable with a default fade animation.

Advanced Features of AnimatedVisibility

To fully utilize AnimatedVisibility, you need to explore its advanced capabilities, including custom animations, staggered transitions, and performance optimization.

1. Custom Enter and Exit Animations

AnimatedVisibility allows you to specify custom animations for entering and exiting views, enabling you to create tailored visual effects.

Example: Custom Slide Animation

AnimatedVisibility(
    visible = isVisible,
    enter = slideInHorizontally { it },
    exit = slideOutHorizontally { -it }
) {
    Box(
        modifier = Modifier
            .size(100.dp)
            .background(Color.Blue)
    )
}

Here, the composable slides in and out horizontally based on its visibility state. The slideInHorizontally and slideOutHorizontally functions define the custom animations.

Combine Multiple Animations

You can combine multiple effects for a more complex transition:

AnimatedVisibility(
    visible = isVisible,
    enter = fadeIn() + scaleIn(),
    exit = fadeOut() + shrinkOut()
) {
    Box(
        modifier = Modifier
            .size(100.dp)
            .background(Color.Green)
    )
}

This example combines fade, scale, and shrink effects for enter and exit animations.

2. Staggered Transitions

Staggered transitions can enhance user experience by animating elements sequentially.

Example: List Animation

@Composable
fun StaggeredListAnimation(items: List<String>) {
    LazyColumn {
        itemsIndexed(items) { index, item ->
            AnimatedVisibility(
                visible = true,
                enter = fadeIn(animationSpec = tween(delayMillis = index * 100))
            ) {
                Text(item, modifier = Modifier.padding(8.dp))
            }
        }
    }
}

In this example, each list item fades in with a delay, creating a cascading effect.

3. AnimatedVisibilityScope

The AnimatedVisibilityScope provides additional tools for animating child composables independently.

Example: Independent Child Animations

AnimatedVisibility(visible = isVisible) {
    Box(modifier = Modifier.size(200.dp).background(Color.Gray)) {
        Text("Top Text", modifier = Modifier.align(Alignment.TopCenter))
        Text("Bottom Text", modifier = Modifier.align(Alignment.BottomCenter))
    }
}

Within the AnimatedVisibilityScope, you can specify custom animations for child elements independently, allowing for complex transitions.

Best Practices for Using AnimatedVisibility

1. Optimize Performance

Animations can impact performance, especially in complex UIs. Follow these tips:

  • Minimize State Changes: Avoid frequent recompositions by limiting state updates.

  • Use Lightweight Effects: Prefer simple animations like fadeIn and fadeOut for better performance.

  • Profile Performance: Use tools like Android Studio Profiler to monitor frame rates and identify bottlenecks.

2. Maintain Consistency

Ensure animations align with the app's overall design language. For instance:

  • Use consistent durations and easing curves.

  • Avoid overly elaborate animations that distract users.

3. Test Across Devices

Test animations on devices with varying screen sizes and performance levels to ensure a smooth experience.

Advanced Use Cases

1. Conditional Animations

You can use AnimatedVisibility for conditional animations based on complex logic.

Example: Dynamic Animations

AnimatedVisibility(
    visible = isVisible,
    enter = fadeIn(animationSpec = spring(stiffness = Spring.StiffnessLow)),
    exit = fadeOut(animationSpec = tween(durationMillis = 500))
) {
    Text("Dynamic Animation", modifier = Modifier.padding(16.dp))
}

Here, the animation behavior changes based on the specified AnimationSpec.

2. Interactive Transitions

AnimatedVisibility can enhance interactive elements like buttons or modals.

Example: Expandable Card

@Composable
fun ExpandableCard(title: String, content: String) {
    var expanded by remember { mutableStateOf(false) }

    Card(modifier = Modifier.padding(8.dp).fillMaxWidth()) {
        Column(
            modifier = Modifier.clickable { expanded = !expanded }
        ) {
            Text(title, style = MaterialTheme.typography.h6)

            AnimatedVisibility(visible = expanded) {
                Text(content, style = MaterialTheme.typography.body1)
            }
        }
    }
}

This example showcases an expandable card where content visibility is controlled dynamically.

Conclusion

AnimatedVisibility is a powerful tool in Jetpack Compose, enabling developers to create polished and dynamic user interfaces. By mastering its advanced features, you can craft delightful animations that enhance your app’s user experience. Remember to balance creativity with performance, and always align animations with your app’s design principles.

Start experimenting with AnimatedVisibility today and elevate your Compose development skills to the next level!

Popular posts from this blog

Restricting Jetpack Compose TextField to Numeric Input Only

Jetpack Compose has revolutionized Android development with its declarative approach, enabling developers to build modern, responsive UIs more efficiently. Among the many components provided by Compose, TextField is a critical building block for user input. However, ensuring that a TextField accepts only numeric input can pose challenges, especially when considering edge cases like empty fields, invalid characters, or localization nuances. In this blog post, we'll explore how to restrict a Jetpack Compose TextField to numeric input only, discussing both basic and advanced implementations. Why Restricting Input Matters Restricting user input to numeric values is a common requirement in apps dealing with forms, payment entries, age verifications, or any data where only numbers are valid. Properly validating input at the UI level enhances user experience, reduces backend validation overhead, and minimizes errors during data processing. Compose provides the flexibility to implement ...

jetpack compose - TextField remove underline

Compose TextField Remove Underline The TextField is the text input widget of android jetpack compose library. TextField is an equivalent widget of the android view system’s EditText widget. TextField is used to enter and modify text. The following jetpack compose tutorial will demonstrate to us how we can remove (actually hide) the underline from a TextField widget in an android application. We have to apply a simple trick to remove (hide) the underline from the TextField. The TextField constructor’s ‘colors’ argument allows us to set or change colors for TextField’s various components such as text color, cursor color, label color, error color, background color, focused and unfocused indicator color, etc. Jetpack developers can pass a TextFieldDefaults.textFieldColors() function with arguments value for the TextField ‘colors’ argument. There are many arguments for this ‘TextFieldDefaults.textFieldColors()’function such as textColor, disabledTextColor, backgroundColor, cursorC...

jetpack compose - Image clickable

Compose Image Clickable The Image widget allows android developers to display an image object to the app user interface using the jetpack compose library. Android app developers can show image objects to the Image widget from various sources such as painter resources, vector resources, bitmap, etc. Image is a very essential component of the jetpack compose library. Android app developers can change many properties of an Image widget by its modifiers such as size, shape, etc. We also can specify the Image object scaling algorithm, content description, etc. But how can we set a click event to an Image widget in a jetpack compose application? There is no built-in property/parameter/argument to set up an onClick event directly to the Image widget. This android application development tutorial will demonstrate to us how we can add a click event to the Image widget and make it clickable. Click event of a widget allow app users to execute a task such as showing a toast message by cli...