Jetpack Compose - Top App Bar

Top app bars display information and actions at the top of a screen.

TopAppBar is similar to that of the Action Bar widget in Android. This is one of the most UI components in Android. The action bar is used to represent the app name and action items in Android. In this article, we will take a look at the implementation of the TopAppBar in Android using Jetpack compose. 



package
com.compose.myapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.compose.myapplication.ui.theme.MyApplicationTheme

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MainContent()
}
}
}
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainContent() {
Scaffold(
topBar = {
SmallTopAppBar(
title = { Text("Simple TopAppBar") },
navigationIcon = {
IconButton(onClick = { }) {
Icon(
imageVector = Icons.Filled.Menu, contentDescription = "Localized description"
)
}
},
actions = {
IconButton(onClick = { }) {
Icon(
imageVector = Icons.Filled.Favorite, contentDescription = "Localized description"
)
}
}
)
},
content = {
val scrollState = rememberScrollState()
val offset by animateDpAsState(targetValue = if (scrollState.value == 0) 15.dp else 0.dp)
Column(
modifier = Modifier
.verticalScroll(scrollState)
.offset(y = offset)
.padding(bottom = 16.dp)
//.background(ScaffoldBackground)
) {
Text(
text = "Get your app ready for M3",
style = MaterialTheme.typography.labelLarge,
modifier = Modifier.padding(horizontal = 28.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Material Design is an adaptable system of guidelines, components, and tools that support the best practices of user interface design. Backed by open-source code, Material Design streamlines collaboration between designers and developers, and helps teams quickly build beautiful products.\n" +
"\n" +
" Make personal devices feel personal with Material Design 3, Google’s most expressive and adaptable design system yet. Coming first to Android 12.\n" +
"\n" +
"\n" +
"\n" +
"\n" +
" Make personal devices feel personal with Material Design 3, Google’s most expressive and adaptable design system yet. Coming first to Android 12.\n" +
"\n" +
"\n" +
"\n" +
"\n" +
" Make personal devices feel personal with Material Design 3, Google’s most expressive and adaptable design system yet. Coming first to Android 12.\n" +
"\n" +
"\n" +
"\n" +
"\n" +
" Make personal devices feel personal with Material Design 3, Google’s most expressive and adaptable design system yet. Coming first to Android 12.\n" +
"\n" +
"\n" +
"\n" +
"\n" +
" Make personal devices feel personal with Material Design 3, Google’s most expressive and adaptable design system yet. Coming first to Android 12.\n" +
"\n" +
"\n" +
"\n" +
"\n" +
" Make personal devices feel personal with Material Design 3, Google’s most expressive and adaptable design system yet. Coming first to Android 12.\n" +
"\n" +
"\n" +
"\n" +
"\n" +
" Less code Do more with less code and avoid entire classes of bugs, so code is simple and easy to maintain.\n",

style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(horizontal = 28.dp)
)
}
}
)
}


  • App Bar Top Simple
  • Center Aligned Top App Bar
  • Pinned Small Top App Bar
  • Enter Always Small Top App Bar
  • Exit Until Collapsed Medium Top App Bar
  • Exit Until Collapsed Large Top App Bar

package com.compose.myapplication

import androidx.compose.animation.rememberSplineBasedDecay
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SmallTopAppBar
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp

/**
* A sample for a simple use of [SmallTopAppBar].
*
* The top app bar here does not react to any scroll events in the content under it.
*/

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SimpleSmallTopAppBar() {
Scaffold(
topBar = {
SmallTopAppBar(
title = { Text("Simple TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
},
actions = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
}
)
},
content = { innerPadding ->
LazyColumn(
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)
)
}
}
}
)
}

/**
* A sample for a simple use of [CenterAlignedTopAppBar].
*
* The top app bar here does not react to any scroll events in the content under it.
*/

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SimpleCenterAlignedTopAppBar() {
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text("Centered TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
},
actions = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
}
)
},
content = { innerPadding ->
LazyColumn(
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)
)
}
}
}
)
}

/**
* A sample for a pinned [SmallTopAppBar].
*
* The top app bar here is pinned to its location and changes its container color when the content
* under it is scrolled.
*/

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PinnedSmallTopAppBar() {
val scrollBehavior = remember { TopAppBarDefaults.pinnedScrollBehavior() }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
SmallTopAppBar(
title = { Text("Small TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
},
actions = {
// RowScope here, so these icons will be placed horizontally
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
},
scrollBehavior = scrollBehavior
)
},
content = { innerPadding ->
LazyColumn(
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)
)
}
}
}
)
}

/**
* A sample for a [SmallTopAppBar] that collapses when the content is scrolled up, and
* appears when the content scrolled down.
*/

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EnterAlwaysSmallTopAppBar() {
val scrollBehavior = remember { TopAppBarDefaults.enterAlwaysScrollBehavior() }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
SmallTopAppBar(
title = { Text("Small TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
},
actions = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
},
scrollBehavior = scrollBehavior
)
},
content = { innerPadding ->
LazyColumn(
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)
)
}
}
}
)
}

/**
* A sample for a [MediumTopAppBar] that collapses when the content is scrolled up, and
* appears when the content is completely scrolled back down.
*/

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExitUntilCollapsedMediumTopAppBar() {
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
val scrollBehavior = remember(decayAnimationSpec) {
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec)
}
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
MediumTopAppBar(
title = { Text("Medium TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
},
actions = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
},
scrollBehavior = scrollBehavior
)
},
content = { innerPadding ->
LazyColumn(
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)
)
}
}
}
)
}

/**
* A sample for a [LargeTopAppBar] that collapses when the content is scrolled up, and
* appears when the content is completely scrolled back down.
*/

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExitUntilCollapsedLargeTopAppBar() {
val decayAnimationSpec = rememberSplineBasedDecay<Float>()
val scrollBehavior = remember(decayAnimationSpec) {
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(decayAnimationSpec)
}
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
LargeTopAppBar(
title = { Text("Large TopAppBar") },
navigationIcon = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Menu,
contentDescription = "Localized description"
)
}
},
actions = {
IconButton(onClick = { /* doSomething() */ }) {
Icon(
imageVector = Icons.Filled.Favorite,
contentDescription = "Localized description"
)
}
},
scrollBehavior = scrollBehavior
)
},
content = { innerPadding ->
LazyColumn(
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)
)
}
}
}
)
}



..

Comments