![](/_next/image?url=https%3A%2F%2Fgoodrequest-web.s3.eu-central-1.amazonaws.com%2Fembeded_games_08_86026c0b38.png&w=3840&q=75)
Embedded games in mobile apps: Make your app more attractive
![](/_next/image?url=https%3A%2F%2Fgoodrequest-web.s3.eu-central-1.amazonaws.com%2FJan_Kandrac_Android_developer_f16fc2438b.jpeg&w=96&q=75)
6. Sep 2021
AndroidJetpack Compose can be future of Android programming. Most of it’s features and composables are easy to use and really simple to understand, others can have huge number of attributes. In Jetpack Compose Basics some of them will be explained. Scaffold will be first of them.
What is Scaffold and how to use it?
Scaffold is a base composable function used in Material applications. This component provides simple way to put together several material components to construct application screen with correct layout behavior ensured. (e.g. correct position of snackbar on the top of floating action button, animations and state of drawer and more)
Scaffold contains slots for TopBar, BottomBar, Snackbar, FloatingActionButton and Drawer. It takes a lots of parameters to customize, but don't be afraid, most of them are pretty obvious and need only simple explanation.
@Composable
fun Scaffold(
modifier: Modifier = Modifier,
scaffoldState: ScaffoldState = rememberScaffoldState(),
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
floatingActionButton: @Composable () -> Unit = {},
floatingActionButtonPosition: FabPosition = FabPosition.End,
isFloatingActionButtonDocked: Boolean = false,
drawerContent: @Composable (ColumnScope.() -> Unit)? = null,
drawerGesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerDefaults.Elevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
drawerScrimColor: Color = DrawerDefaults.scrimColor,
backgroundColor: Color = MaterialTheme.colors.background,
contentColor: Color = contentColorFor(backgroundColor),
content: @Composable (PaddingValues) -> Unit
)
@Composable
fun Scaffold(
modifier: Modifier = Modifier,
scaffoldState: ScaffoldState = rememberScaffoldState(),
topBar: @Composable () -> Unit = {},
bottomBar: @Composable () -> Unit = {},
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) },
floatingActionButton: @Composable () -> Unit = {},
floatingActionButtonPosition: FabPosition = FabPosition.End,
isFloatingActionButtonDocked: Boolean = false,
drawerContent: @Composable (ColumnScope.() -> Unit)? = null,
drawerGesturesEnabled: Boolean = true,
drawerShape: Shape = MaterialTheme.shapes.large,
drawerElevation: Dp = DrawerDefaults.Elevation,
drawerBackgroundColor: Color = MaterialTheme.colors.surface,
drawerContentColor: Color = contentColorFor(drawerBackgroundColor),
drawerScrimColor: Color = DrawerDefaults.scrimColor,
backgroundColor: Color = MaterialTheme.colors.background,
contentColor: Color = contentColorFor(backgroundColor),
content: @Composable (PaddingValues) -> Unit
)
Now, it's time to discuss non-trivial but still fairly simple parameters.
topBar: @Composable () -> Unit = {}
Optional parameter. As you can see in definition, you should provide composable function that will fill the slot at the top of the screen. Either predefined TopAppBar composable can be used or you can use your own implementation to match custom designs. Default value is empty lambda, in this case no topBar is used. This snippet of code implements TopAppBar passed to topBar parameter.
topBar = {
TopAppBar(
title = { Text(text = "Title text") },
navigationIcon = {
Icon(modifier = padding, imageVector = Icons.Default.ArrowBack, contentDescription = "Back")
},
actions = {
Icon(modifier = padding, imageVector = Icons.Default.Favorite, contentDescription = "Favorite")
Icon(modifier = padding, imageVector = Icons.Default.Search, contentDescription = "Search")
}
)
}
bottomBar: @Composable () -> Unit = {}
Optional parameter. In this case, composable function is needed that will fill the slot at the bottom of the screen. Predefined composables like BottomAppBar or BottomNavigation can be used, but these are really just recommendations. You can pass own custom composable. This snippet of code implements BottomAppBar passed to bottomBar parameter.
bottomBar = {
BottomAppBar(
content = {
Icon(modifier = padding, imageVector = Icons.Default.Menu, contentDescription = "Menu")
Icon(modifier = padding, imageVector = Icons.Default.Search, contentDescription = "Search")
Text(text = "Anything can be here")
}
)
}
floatingActionButton: @Composable () -> Unit = {}
Optional parameter. Floating action button (FAB) represents the primary action of a screen.It can be configured also by floatingActionButtonPosition (Center or End) and isFloatingActionButtonDocked (boolean, whether the FAB should overlap with BottomBar). Preferred composable for this slot is FloatingActionButton, but you can use any composable function. This snippet of code implements FloatingActionButton passed to floatingActionButton parameter.
floatingActionButton = {
FloatingActionButton(
onClick = {},
content = {
Icon(imageVector = Icons.Default.Favorite,contentDescription = "")
}
)
}
drawerContent: @Composable (ColumnScope.() -> Unit)? = null
Optional parameter. Drawer sheet represents content that can be pulled from left (or right for RTL). Drawer can be also showed by using scaffoldState.drawerState.open() function in coroutine scope. Lambda which is needed here is already extension function of ColumnScope, so every composable which will be used in lambda will be placed like in Column (from top to bottom). Animation, scrim of background and swiping is all handled by Scaffold. This snippet of code implements 4 items passed to drawerContent parameter.
drawerContent = {
Icon(
modifier = Modifier.padding(16.dp),
imageVector = Icons.Default.Person,
contentDescription = ""
)
Text(modifier = Modifier.padding(16.dp), text = "First line")
Text(modifier = Modifier.padding(16.dp), text = "Second line")
Text(modifier = Modifier.padding(16.dp), text = "Third line")
}
snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) }
Snackbar is a little more complicated. We can use snackbarHost parameter when we want custom look of Snackbar else the default design and behavior implemented in SnackbarHost is used. We can let SnackbarHost to do it's work for now.Snackbars provide brief messages about app processes at the bottom of the screen. In our example snippet, the Snackbar is shown when FAB is clicked.
val scope = rememberCoroutineScope()
val scaffoldState = rememberScaffoldState()
.
.
.
scaffoldState = scaffoldState,
floatingActionButton = {
FloatingActionButton(
onClick = {
scope.launch {
scaffoldState.snackbarHostState.showSnackbar("Hello there!")
}
},
content = {
Icon(imageVector = Icons.Default.Favorite, contentDescription = "")
}
)
}
Few things to mention. showSnackbar(...) is suspend function thus coroutine scope is needed. We can get composition bounded one simply by using rememberCoroutineScope(). SnackbarHost guarantees to show at most one snackbar at a time, others will be queued.
content: @Composable (PaddingValues) -> Unit
Remaining area on the screen. You can use any composable function here. The lambda receives PaddingValues that should be applied to the content root via Modifier.padding to properly offset top and bottom bars.
Full Scaffold with all widgets can look like this