TopAppBar Customization: Mastering UI in Jetpack Compose

In Jetpack Compose, the TopAppBar (now known as CenterAlignedTopAppBar, TopAppBar or MediumTopAppBar depending on the desired design) serves as a crucial element for displaying titles, navigation icons, and actions at the top of your application screen. Customizing the TopAppBar enhances the user interface, providing a tailored and branded experience. This blog post delves into various customization options for the TopAppBar in Jetpack Compose, offering code examples and best practices.

What is a TopAppBar in Jetpack Compose?

The TopAppBar is a composable function that renders a toolbar at the top of the screen. It typically includes a title, a navigation icon (e.g., a back button or menu icon), and action items (e.g., search or settings icons). Compose offers multiple variants of TopAppBar which are intended to target different UI patterns and screen sizes.

Why Customize the TopAppBar?

  • Branding: Incorporate your app’s color scheme and logo.
  • Functionality: Add custom action icons for frequent user tasks.
  • User Experience: Improve navigation and information presentation.
  • Adaptability: Adjust the appearance based on screen size and orientation.

How to Customize the TopAppBar

Jetpack Compose offers numerous ways to customize the TopAppBar to fit your application’s specific needs. We’ll cover several key customization options.

1. Basic TopAppBar Implementation

First, let’s start with a basic implementation of the TopAppBar to establish a foundation.


import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun SimpleTopAppBar() {
    TopAppBar(
        title = { Text("My App") },
        navigationIcon = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(Icons.Filled.Menu, contentDescription = "Menu")
            }
        },
        actions = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(Icons.Default.Menu, contentDescription = "Settings")
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
fun SimpleTopAppBarPreview() {
    SimpleTopAppBar()
}

This example displays a simple TopAppBar with a title, a menu icon on the left, and a settings icon on the right.

2. Changing Colors and Styling

You can customize the colors of the TopAppBar to match your application’s theme.


import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun CustomizedTopAppBar() {
    TopAppBar(
        title = { Text("Customized App", color = Color.White) },
        backgroundColor = Color.DarkGray,
        contentColor = Color.White, // For icons and other content
        navigationIcon = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(Icons.Filled.ArrowBack, contentDescription = "Back", tint = Color.White)
            }
        },
        actions = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(Icons.Filled.ArrowBack, contentDescription = "Settings", tint = Color.White)
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
fun CustomizedTopAppBarPreview() {
    CustomizedTopAppBar()
}

In this example, the background color is set to dark gray, and the title and icon colors are set to white. You can also utilize contentColor to consistently style interactive elements.

3. Adding Custom Actions

You can add custom action items to the TopAppBar based on your app’s functionality. For example, a search icon, a share icon, or any other custom action.


import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Share
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun ActionsTopAppBar() {
    TopAppBar(
        title = { Text("Action App") },
        actions = {
            IconButton(onClick = { /*TODO: Implement search action*/ }) {
                Icon(Icons.Filled.Search, contentDescription = "Search")
            }
            IconButton(onClick = { /*TODO: Implement share action*/ }) {
                Icon(Icons.Filled.Share, contentDescription = "Share")
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
fun ActionsTopAppBarPreview() {
    ActionsTopAppBar()
}

This example adds a search and a share icon to the actions area of the TopAppBar.

4. Using Custom Navigation Icon

Replace the default navigation icon with a custom one, like an app logo or a different type of navigation control.


import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun NavigationTopAppBar() {
    TopAppBar(
        title = { Text("Navigation App") },
        navigationIcon = {
            IconButton(onClick = { /*TODO: Navigate to home*/ }) {
                Icon(Icons.Filled.Home, contentDescription = "Home")
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
fun NavigationTopAppBarPreview() {
    NavigationTopAppBar()
}

Here, the navigation icon is set to a home icon, indicating a navigation action to the home screen.

5. Elevation Customization

Adjust the elevation of the TopAppBar to provide a visual hierarchy and emphasize its importance on the screen.


import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import androidx.compose.ui.tooling.preview.Preview

@Composable
fun ElevationTopAppBar() {
    TopAppBar(
        title = { Text("Elevation App") },
        elevation = 10.dp, // Adjust elevation as needed
        actions = {
            IconButton(onClick = { /*TODO*/ }) {
                Icon(Icons.Filled.Settings, contentDescription = "Settings")
            }
        }
    )
}

@Preview(showBackground = true)
@Composable
fun ElevationTopAppBarPreview() {
    ElevationTopAppBar()
}

By setting elevation = 10.dp, you lift the TopAppBar slightly above the content, providing a subtle visual cue.

6. Centered Title

For a centered title, use the `CenterAlignedTopAppBar` composable:


import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun CenterAlignedTopAppBarExample() {
    CenterAlignedTopAppBar(
        title = { Text("Centered Title") },
        navigationIcon = {
            IconButton(onClick = { /* doSomething() */ }) {
                Icon(
                    imageVector = Icons.Filled.Menu,
                    contentDescription = "Localized description"
                )
            }
        },
        actions = {
            IconButton(onClick = { /* doSomething() */ }) {
                Icon(
                    imageVector = Icons.Filled.Menu,
                    contentDescription = "Localized description"
                )
            }
        }
    )
}

@Preview
@Composable
fun CenterAlignedTopAppBarPreview() {
    CenterAlignedTopAppBarExample()
}

This example shows the title text centered in the top app bar.

7. Integrating with Navigation Components

To use TopAppBar effectively, integrate it with your navigation components. Display different titles and icons based on the current screen.


import androidx.compose.material.*
import androidx.compose.runtime.Composable

@Composable
fun ScreenWithTopAppBar(
    title: String,
    navigationIcon: @Composable (() -> Unit)? = null,
    actions: @Composable (RowScope.() -> Unit) = {}
) {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text(title) },
                navigationIcon = navigationIcon,
                actions = actions
            )
        }
    ) {
        // Your screen content here
    }
}

In this flexible setup, your content can vary depending on screen-specific data:


import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.runtime.Composable

@Composable
fun DetailsScreen() {
    ScreenWithTopAppBar(
        title = "Details",
        navigationIcon = {
            IconButton(onClick = { /* Handle back navigation */ }) {
                Icon(Icons.Filled.ArrowBack, contentDescription = "Back")
            }
        }
    ) {
        // Add detail specific actions here
    }
}

Use this pattern for various screens in your app.

Best Practices for TopAppBar Customization

  • Consistency: Maintain a consistent style across all screens.
  • Accessibility: Provide proper content descriptions for all icons.
  • Context: Ensure actions are relevant to the current screen.
  • Testing: Test on various screen sizes and orientations.
  • Theming: Leverage Jetpack Compose’s theming capabilities to create dynamic themes.

Conclusion

Customizing the TopAppBar in Jetpack Compose enhances both the aesthetics and functionality of your Android applications. By leveraging these customization techniques, you can create a tailored and intuitive user interface. Tailor the TopAppBar to match your application’s identity, making navigation and key features readily accessible.