Build apps faster with our new App builder! Check it out →

HorizontalFloatingAppBar

Common

Component in Material 3 Compose

Last updated:

Installation

dependencies {
   implementation("androidx.compose.material3:material3:1.4.0-alpha02")
}

Overloads

@ExperimentalMaterial3ExpressiveApi
@Composable
fun HorizontalFloatingAppBar(
    expanded: Boolean,
    modifier: Modifier = Modifier,
    containerColor: Color = FloatingAppBarDefaults.ContainerColor,
    contentPadding: PaddingValues = FloatingAppBarDefaults.ContentPadding,
    scrollBehavior: FloatingAppBarScrollBehavior? = null,
    shape: Shape = FloatingAppBarDefaults.ContainerShape,
    leadingContent: @Composable (RowScope.() -> Unit)? = null,
    trailingContent: @Composable (RowScope.() -> Unit)? = null,
    content: @Composable RowScope.() -> Unit
)

Parameters

namedescription
expandedwhether the FloatingAppBar is in expanded mode, i.e. showing [leadingContent] and [trailingContent].
modifierthe [Modifier] to be applied to this FloatingAppBar.
containerColorthe color used for the background of this FloatingAppBar. Use [Color.Transparent] to have no color.
contentPaddingthe padding applied to the content of this FloatingAppBar.
scrollBehaviora [FloatingAppBarScrollBehavior]. If null, this FloatingAppBar will not automatically react to scrolling.
shapethe shape used for this FloatingAppBar.
leadingContentthe leading content of this FloatingAppBar. The default layout here is a [Row], so content inside will be placed horizontally. Only showing if [expanded] is true.
trailingContentthe trailing content of this FloatingAppBar. The default layout here is a [Row], so content inside will be placed horizontally. Only showing if [expanded] is true.
contentthe main content of this FloatingAppBar. The default layout here is a [Row], so content inside will be placed horizontally.

Code Examples

ExpandableHorizontalFloatingAppBar

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun ExpandableHorizontalFloatingAppBar() {
    val context = LocalContext.current
    val isTouchExplorationEnabled = remember {
        val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
        am.isEnabled && am.isTouchExplorationEnabled
    }
    val listState = rememberLazyListState()
    var currentItem = 0
    val expanded by remember {
        derivedStateOf {
            val temp = currentItem
            currentItem = listState.firstVisibleItemIndex
            listState.firstVisibleItemIndex {'<='} temp // true if the list is scrolled up
        }
    }
    Scaffold(
        content = { innerPadding ->
            Box {
                LazyColumn(
                    state = listState,
                    contentPadding = innerPadding,
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    val list = (0..75).map { it.toString() }
                    items(count = list.size) {
                        Text(
                            text = list[it],
                            style = MaterialTheme.typography.bodyLarge,
                            modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                        )
                    }
                }
                HorizontalFloatingAppBar(
                    modifier = Modifier.align(BottomCenter).offset(y = -ScreenOffset),
                    expanded = expanded || isTouchExplorationEnabled,
                    leadingContent = { leadingContent() },
                    trailingContent = { trailingContent() },
                    content = {
                        FilledIconButton(
                            modifier = Modifier.width(64.dp),
                            onClick = { /* doSomething() */ }
                        ) {
                            Icon(Icons.Filled.Add, contentDescription = "Localized description")
                        }
                    },
                )
            }
        }
    )
}

ScrollableHorizontalFloatingAppBar

@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun ScrollableHorizontalFloatingAppBar() {
    val context = LocalContext.current
    val isTouchExplorationEnabled = remember {
        val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
        am.isEnabled && am.isTouchExplorationEnabled
    }
    val listState = rememberLazyListState()
    val exitAlwaysScrollBehavior =
        FloatingAppBarDefaults.exitAlwaysScrollBehavior(exitDirection = Bottom)
    Scaffold(
        modifier = Modifier.nestedScroll(exitAlwaysScrollBehavior),
        content = { innerPadding ->
            Box {
                LazyColumn(
                    state = listState,
                    contentPadding = innerPadding,
                    verticalArrangement = Arrangement.spacedBy(8.dp)
                ) {
                    val list = (0..75).map { it.toString() }
                    items(count = list.size) {
                        Text(
                            text = list[it],
                            style = MaterialTheme.typography.bodyLarge,
                            modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
                        )
                    }
                }
                HorizontalFloatingAppBar(
                    modifier = Modifier.align(BottomCenter).offset(y = -ScreenOffset),
                    expanded = true,
                    leadingContent = { leadingContent() },
                    trailingContent = { trailingContent() },
                    content = {
                        FilledIconButton(
                            modifier = Modifier.width(64.dp),
                            onClick = { /* doSomething() */ }
                        ) {
                            Icon(Icons.Filled.Add, contentDescription = "Localized description")
                        }
                    },
                    scrollBehavior =
                        if (!isTouchExplorationEnabled) exitAlwaysScrollBehavior else null,
                )
            }
        }
    )
}
by @alexstyl