Skip to content

TopAppBar

TopAppBar is a top application bar component in COUI, used to provide navigation, title, and action buttons at the top of the interface. It supports both large title and regular modes, as well as dynamic effects during scrolling.

This component is typically used in conjunction with the Scaffold component to maintain consistent layout and behavior across different pages in the application.

Import

kotlin
import io.github.suqi8.coui.kmp.basic.TopAppBar
import io.github.suqi8.coui.kmp.basic.SmallTopAppBar
import io.github.suqi8.coui.kmp.basic.COUIScrollBehavior
import io.github.suqi8.coui.kmp.basic.rememberTopAppBarState

Basic Usage

Small TopAppBar

kotlin
Scaffold(
    topBar = {
        SmallTopAppBar(
            title = "Title",
            navigationIcon = {
                IconButton(onClick = { /* Handle click event */ }) {
                    Icon(COUIIcons.Back, contentDescription = "Back")
                }
            },
            actions = {
                IconButton(onClick = { /* Handle click event */ }) {
                    Icon(COUIIcons.More, contentDescription = "More")
                }
            }
        )
    }
)

Large TopAppBar

kotlin
Scaffold(
    topBar = {
        TopAppBar(
            title = "Title",
            largeTitle = "Large Title", // If not specified, title value will be used
            navigationIcon = {
                IconButton(onClick = { /* Handle click event */ }) {
                    Icon(COUIIcons.Back, contentDescription = "Back")
                }
            },
            actions = {
                IconButton(onClick = { /* Handle click event */ }) {
                    Icon(COUIIcons.More, contentDescription = "More")
                }
            }
        )
    }
)

With Subtitle

Both bars can show a subtitle below the title. On the collapsible TopAppBar the subtitle fades out while the bar collapses by default; set hideSubtitleOnCollapse = false to keep it visible and slide it into the collapsed bar below the title:

kotlin
TopAppBar(
    title = "Title",
    largeTitle = "Large Title",
    subtitle = "Subtitle",
    hideSubtitleOnCollapse = false
)

Large TopAppBar Scroll Behavior (Using Scaffold)

TopAppBar supports changing its display state when content scrolls:

kotlin
val scrollBehavior = COUIScrollBehavior()

Scaffold(
    topBar = {
        TopAppBar(
            title = "Title",
            largeTitle = "Large Title", // If not specified, title value will be used
            scrollBehavior = scrollBehavior
        )
    }
) { paddingValues ->
    // Content area needs to consider padding
    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            // If you want to add the overscroll effect, please add it before the scroll behavior
            .overScrollVertical()
            // Bind TopAppBar scroll behavior
            .nestedScroll(scrollBehavior.nestedScrollConnection),
        contentPadding = PaddingValues(top = paddingValues.calculateTopPadding())
    ) {
        // List content
    }
}

Custom Styles

Custom Colors

kotlin
TopAppBar(
    title = "Title",
    color = COUITheme.colorScheme.primary,
    titleColor = COUITheme.colorScheme.onPrimary,
    largeTitleColor = COUITheme.colorScheme.onPrimary
)

Custom Content Padding

kotlin
TopAppBar(
    title = "Title",
    titlePadding = 32.dp
)

Custom Icon Padding

kotlin
TopAppBar(
    title = "Title",
    navigationIconPadding = 12.dp,
    actionIconPadding = 12.dp
)

Properties

TopAppBar Properties

Property NameTypeDescriptionDefault ValueRequired
titleStringTop bar title-Yes
modifierModifierModifier applied to the top barModifierNo
colorColorTop bar background colorCOUITheme.colorScheme.surfaceNo
titleColorColorColor of the collapsed small title textCOUITheme.colorScheme.onSurfaceNo
largeTitleStringLarge title texttitleNo
largeTitleColorColorColor of the expanded large title textCOUITheme.colorScheme.onSurfaceNo
subtitleStringSubtitle text displayed below the title bar""No
subtitleColorColorColor of the subtitle textCOUITheme.colorScheme.onSurfaceVariantSummaryNo
dividerColorColorColor of the bottom hairline divider revealed while collapsingCOUITheme.colorScheme.dividerLineNo
navigationIcon@Composable () -> UnitComposable function for navigation icon area{}No
actions@Composable RowScope.() -> UnitComposable function for action buttons area (24dp icons recommended){}No
scrollBehaviorScrollBehavior?Controls top bar scroll behaviornullNo
defaultWindowInsetsPaddingBooleanWhether to apply default window insets paddingtrueNo
showDividerBooleanWhether to draw the bottom hairline divider that fades in as the bar collapsestrueNo
hideSubtitleOnCollapseBooleanWhether the subtitle fades out while the bar collapses; when false it stays opaque and slides into the collapsed bar below the titletrueNo
titlePaddingDpHorizontal content paddingTopAppBarDefaults.TitlePaddingNo
navigationIconPaddingDpStart padding of the navigation iconTopAppBarDefaults.NavigationIconPaddingNo
actionIconPaddingDpEnd padding of the action iconsTopAppBarDefaults.ActionIconPaddingNo
bottomContent@Composable () -> UnitComposable content displayed below the title bar area{}No

SmallTopAppBar Properties

Property NameTypeDescriptionDefault ValueRequired
titleStringTop bar title-Yes
modifierModifierModifier applied to the top barModifierNo
colorColorTop bar background colorCOUITheme.colorScheme.surfaceNo
titleColorColorColor of the title textCOUITheme.colorScheme.onSurfaceNo
subtitleStringSubtitle text displayed below the title bar""No
subtitleColorColorColor of the subtitle textCOUITheme.colorScheme.onSurfaceVariantSummaryNo
dividerColorColorColor of the bottom hairline divider revealed on scrollCOUITheme.colorScheme.dividerLineNo
navigationIcon@Composable () -> UnitComposable function for navigation icon area{}No
actions@Composable RowScope.() -> UnitComposable function for action buttons area (24dp icons recommended){}No
scrollBehaviorScrollBehavior?Controls top bar scroll behaviornullNo
defaultWindowInsetsPaddingBooleanWhether to apply default window insets paddingtrueNo
showDividerBooleanWhether to draw the bottom hairline divider as content scrolls beneath the bar (requires scrollBehavior)trueNo
titlePaddingDpHorizontal content paddingTopAppBarDefaults.TitlePaddingNo
navigationIconPaddingDpStart padding of the navigation iconTopAppBarDefaults.NavigationIconPaddingNo
actionIconPaddingDpEnd padding of the action iconsTopAppBarDefaults.ActionIconPaddingNo
bottomContent@Composable () -> UnitComposable content displayed below the title bar area{}No

TopAppBarDefaults Object

The TopAppBarDefaults object provides default values for TopAppBar and SmallTopAppBar components.

Constants

Constant NameTypeDescriptionDefault Value
TitlePaddingDpHorizontal padding of the title and large title16.dp
LargeTitleTopPaddingDpTop padding of the expanded large title54.dp
NavigationIconPaddingDpStart padding of the navigation icon16.dp
ActionIconPaddingDpEnd padding of the action icons16.dp
CollapsedHeightDpCollapsed height of the TopAppBar52.dp
ExpandedHeightDpMinimum expanded height of the TopAppBar without a subtitle107.dp
SmallTopAppBarCenterHeightDpVertical center height for SmallTopAppBar layout52.dp
LargeTitleBottomPaddingDpBottom padding below the large title block when expanded (interpolates to 0.dp as the bar collapses)12.dp
SubtitleBottomPaddingDpBottom padding below the subtitle when it overflows the collapsed bar8.dp
SubtitleMarginTopDpVertical gap between the title and the subtitle3.5.dp
NavigationIconGapDpHorizontal gap between the navigation icon and the collapsed title4.dp
ActionIconGapDpHorizontal gap between the title and the action icons8.dp

ScrollBehavior

COUIScrollBehavior is a configuration object used to control the scroll behavior of the top bar.

rememberTopAppBarState

Used to create and remember TopAppBarState:

kotlin
val scrollBehavior = COUIScrollBehavior(
    state = rememberTopAppBarState(),
    canScroll = { true }
)
Parameter NameTypeDefault ValueDescription
stateTopAppBarStaterememberTopAppBarState()State object controlling scroll state
canScroll() -> BooleanCallback to control whether scrolling is allowed
snapAnimationSpecAnimationSpec<Float>?180ms decelerate tweenDefines the snap to fully expanded/collapsed when scrolling stops midway
flingAnimationSpecDecayAnimationSpec<Float>?rememberSplineBasedDecay()Defines decay animation for fling

Advanced Usage

Handling Window Insets

kotlin
TopAppBar(
    title = "Title",
    largeTitle = "Large Title",
    defaultWindowInsetsPadding = false // Handle window insets manually
)

Custom Scroll Behavior Animation

kotlin
var isScrollingEnabled by remember { mutableStateOf(true) }
val scrollBehavior = COUIScrollBehavior(
    snapAnimationSpec = tween(durationMillis = 100),
    flingAnimationSpec = rememberSplineBasedDecay(),
    canScroll = { isScrollingEnabled } // Can dynamically control whether scrolling is allowed
)

TopAppBar(
    title = "Title",
    largeTitle = "Large Title",
    scrollBehavior = scrollBehavior
)

Combining Large and Small Titles

kotlin
var useSmallTopBar by remember { mutableStateOf(false) }

Box(modifier = Modifier.fillMaxSize()) {
    if (useSmallTopBar) {
        SmallTopAppBar(
            title = "Compact Mode",
            navigationIcon = {
                IconButton(onClick = { useSmallTopBar = false }) {
                    Icon(
                        imageVector = COUIIcons.Back,
                        contentDescription = "Switch to Large Title",
                        tint = COUITheme.colorScheme.onBackground
                    )
                }
            }
        )
    } else {
        TopAppBar(
            title = "Title",
            largeTitle = "Expanded Mode",
            navigationIcon = {
                IconButton(onClick = { useSmallTopBar = true }) {
                    Icon(
                        imageVector = COUIIcons.Back,
                        contentDescription = "Switch to Small Title",
                        tint = COUITheme.colorScheme.onBackground
                    )
                }
            }
        )
    }
}

Changelog

Released under the Apache-2.0 License