Jetpack Compose — Chapter 13: Using a Scaffold Layout
Introduction
Hi, code wizards!!!
When building applications, a design system can be your best friend. This is a pre-prepared collection of reusable elements, all guided by clear standards, which can be brought together to speedily construct any number of apps, saving time and effort.
So when I started to study scaffolding, I wasn't sure why I just had to use it. That will be another topic — let’s focus on how to use it in this article.
As I mentioned, form some time I will try to include one YouTube video, including relevant info/tutorials on live coding. There are many of them, but let’s try to choose one. Watch the movie, and check the code in that article to move forward!
Our Enchanted Journey Through Jetpack Compose
Before we start, please look at where we are in our chapter list so you can explore what more that collection of articles will give you.
A Little Bit of History
Unfortunately, this time, we must speak about the past; it will be hard to understand why we need a Scaffold.
In the realm of Android, we have an incredible resource in the Material Design system.
Google launched Material Design in 2014, and it’s been a game changer ever since.
It provides us with a framework to create stunning, bold, and consistent digital products. The system is not confined only to Android; it can also assist in building high-quality digital experiences for iOS, Flutter, and the web.
Material Design is now upgraded to its third iteration, a significant update to the system announced at Google I/O 2021.
This version is loaded with several components that are indispensable when it comes to building our apps. These components have equivalent Composables, which include:
I’ve touched upon a few in the past, and today I will be introducing some more. We can access all these components by opting for the material library.
Jetpack Compose — Chapter 9: Simple Guide to Adding a TextField
A straightforward guide to seamlessly integrating TextFields into your Jetpack Compose UI
Card
Let me start with a card, a vital component that acts as an entry point to detailed information.
Cards can host a mix of photos, text, and links related to a single subject, accommodating different-sized content. This is where the Card Composable in the material library comes in handy.
The Card in Jetpack Compose is essentially a surface colored background with elevation, meant to display content. Its key parameters include:
领英推荐
Alright, let’s proceed to encapsulate our TextField for search within an elegant Card Composable.
@ExperimentalMaterial3Api
@Composable
fun ArcaneSearchOrb() {
// The mystical card that harbors our spellbound search abilities
Card(
modifier = Modifier
.fillMaxWidth()
.height(75.dp) // The height of our orb, contained yet powerful
.padding(horizontal = 16.dp, vertical = 10.dp), // Ensconced within ethereal padding
shape = RoundedCornerShape(50.dp), // A perfectly rounded orb, smooth and inviting
) {
// The core of our orb, where the magic of searching begins
TextField(
modifier = Modifier.fillMaxSize(), // The TextField spans the entire orb
value = "", // The incantation to summon the search terms remains unspoken
onValueChange = { /* The magic reacts, changing with each keystroke */ },
leadingIcon = {
// The icon that calls forth the vision, a magnifying glass to peer into the depths
Image(painter = painterResource(id = R.drawable.ic_magnify), contentDescription = "Scry for items")
},
trailingIcon = {
// The icon that conjures filters, allowing the seeker to refine their quest
Image(painter = painterResource(id = R.drawable.ic_spell_filter), contentDescription = "Conjure filters")
},
placeholder = {
// The guiding text, a whisper of encouragement to those who seek
Text(
text = "Scry for arcane ingredients...",
modifier = Modifier.fillMaxHeight(),
textAlign = TextAlign.Center, // Centered, as all things should be
)
},
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent, // Invisible bounds, for the focus is within
unfocusedIndicatorColor = Color.Transparent, // Unseen, as the orb's magic is self-contained
),
)
}
}
Think of a floating action button (FAB) as an interactive circular button that triggers the primary action within your app’s UI.
The feature of this button is that it hovers above the interface displaying content, typically situated at a screen corner.
FloatingActionButton
Jetpack Compose facilitates the creation of a floating action button using the FloatingActionButton Composable.
The FloatingActionButton insists on one mandatory parameter:
Moreover, there are a host of optional arguments that you can add:
Let’s revamp our EnchantedMorsel Composable to incorporate a FloatingActionButton in lieu of a Button.
@Composable
fun EnchantedMorsel(
morsel: Morsel, // Our mystical food entity, brimming with properties
enchantmentId: Int = 0, // An optional enchantment to bestow unique powers
) {
Card(
modifier = Modifier
.width(200.dp) // The width of our magical tome
.clickable { /* Invoke a spell upon touch */ }
.padding(end = 8.dp), // Ensuring the tome sits perfectly on the mystical shelf
shape = RoundedCornerShape(corner = CornerSize(10.dp)) // Softened edges to avoid paper cuts from the ether
) {
Column(modifier = Modifier
.padding(bottom = 5.dp)
.fillMaxWidth()) { // The structure of our spell
Image(
modifier = Modifier
.fillMaxWidth()
.height(150.dp), // The visual representation of our morsel
painter = painterResource(id = morsel.image),
contentDescription = "Morsel's visage",
contentScale = ContentScale.Crop // Ensuring the image is as enticing as the morsel itself
)
Spacer(
modifier = Modifier
.fillMaxWidth()
.height(8.dp)) // A breath between the visual and the details
Column(
modifier = Modifier
.padding(horizontal = 5.dp)
.fillMaxWidth()) { // Where the details of the morsel are unveiled
Text(
modifier = Modifier,
text = morsel.name, // The name of our delectable morsel
style = MaterialTheme.typography.subtitle1,
fontWeight = FontWeight.Bold) // Bold, as bold as the flavors
Row(
modifier = Modifier
.padding(top = 5.dp),
verticalAlignment = Alignment.CenterVertically) { // A row for time, as even in magic, preparation takes a moment
Image(
painter = painterResource(id = R.drawable.ic_time),
contentDescription = "Preparation Time",
colorFilter = ColorFilter.tint(
color = MaterialTheme.colors.onSecondary
) // Ensuring the icon matches the theme of the tome
)
Text(
modifier = Modifier.padding(start = 3.dp),
text = "${morsel.preparationTime} mins", // The time it takes to conjure this morsel into existence
style = MaterialTheme.typography.body2)
}
Spacer(modifier = Modifier.height(2.dp)) // A slight pause before the final revelation
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 4.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically) { // A row for price and the magical addition button
Text(
text = "$${morsel.price}", // The cost, in gold or gems, for this morsel
fontWeight = FontWeight.Bold,
style = MaterialTheme.typography.subtitle1
)
FloatingActionButton(
onClick = { /* A spell to add the morsel to your feast */ },
shape = CircleShape,
containerColor = MaterialTheme.colors.secondary) { // A button, as round as a cauldron, to add the morsel
Image(
painter = painterResource(id = R.drawable.ic_plus),
contentDescription = "Add to Feast",
colorFilter = ColorFilter.tint(
color = contentColorFor(MaterialTheme.colors.secondary))) // The plus sign, the universal symbol of addition
}
}
}
}
}
}
Scaffold
Finally, the Scaffold Composable is an essential layout component that materializes the basic design and structure of the material interface. It's the go-to layout component for constructing the broader structure of a screen in your app.
The Scaffold Composable provides placeholders for the following components:
App Bars App Bars, which showcase essential data and operations relative to the active screen, sit comfortably at the top or bottom. The Scaffold Composable earmarks are placeholders for both the top and bottom app bars.
Floating Action Button Floating action buttons prompt the primary action in your UI and the Scaffold Composable provides a spot for it.
content With the content slot, you can define the main content of the screen. It is of type @Composable (PaddingValues) -> Unit and isn't preconfigured.
The PaddingValues parameter enables you to set padding for the content. Its type is PaddingValues and defaults to PaddingValues(0.dp).
Drawer The drawer slot lets you specify the screen's drawer. It is of type @Composable () -> Unit without a preset value.
@Preview(showBackground = true)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen() {
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = { UserBar() },
bottomBar = {
Text(text = "Lower Bar")
}){ paddingValues ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues = paddingValues),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
){
Text(text = "Welcome!")
}
}
}
In this segment, we’ve tackled the execution of a few additional Material 3 components in our application, thereby gaining a deeper understanding of the Scaffold Layout’s operation.
It wasn’t so difficult — wasn’t it?
Let’s prepare for our subsequent part, where we’ll explore the world of displaying a sequence of items on the screen with lazy layouts.