Chapter 19
Chapter 19
Because the DemoScreen contains state, it is considered to be a stateful composable. Now consider the
DemoSlider composable which reads as follows:
@Composable
151
Composable Functions Overview
fun DemoSlider(sliderPosition: Float, onPositionChange : (Float) -> Unit ) {
Slider(
modifier = Modifier.padding(10.dp),
valueRange = 20f..40f,
value = sliderPosition,
onValueChange = onPositionChange
)
}
Although this composable is passed and makes use of the state value stored by the DemoScreen, it does not itself
store any state value. DemoSlider is, therefore, considered to be a stateless composable function.
The topic of state will be covered in greater detail in the chapter entitled “An Overview of Compose State and
Recomposition”.
Composables may also be implemented to accept parameters. The following function accepts text, font weight,
and color parameters and passes them to the built-in Text composable. The fragment also includes a preview
composable to demonstrate how the CustomText function might be called:
@Composable
fun CustomText(text: String, fontWeight: FontWeight, color: Color) {
Text(text = text, fontWeight = fontWeight, color = color)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
CustomText(text = "Hello Compose", fontWeight = FontWeight.Bold,
color = Color.Magenta)
}
When previewed, magenta-colored bold text reading “Hello Compose” will be rendered in the preview panel.
Just about any Kotlin logic code may be included in the body of a composable function. The following composable,
for example, displays different text within a Column depending on the setting of a built-in Switch composable:
@Composable
152
Composable Functions Overview
fun CustomSwitch() {
Column {
Switch(
checked = checked.value,
onCheckedChange = { checked.value = it }
)
if (checked.value) {
Text("Switch is On")
} else {
Text("Switch is Off")
}
}
}
In the above example, we have declared a state value named checked initialized to true and then constructed a
Column containing a Switch composable. The state of the Switch is based on the value of checked and a lambda
assigned as the onCheckedChanged event handler. This lambda sets the checked state to the current Switch setting.
Finally, an if statement is used to decide which of two Text composables are displayed depending on the current
value of the checked state. When run, the text displayed will alternate between “Switch is on” and “Switch is off ”:
Figure 19-1
Similarly, we could use looping syntax to iterate through the items in a list and display them in a Column
separated by instances of the Divider composable:
@Composable
fun CustomList(items: List<String>) {
Column {
for (item in items) {
Text(item)
Divider(color = Color.Black)
}
}
}
153
Composable Functions Overview
MyApplicationTheme {
CustomList(listOf("One", "Two", "Three", "Four", "Five", "Six"))
}
}
Once built and refreshed, the composable will appear in the Preview panel as shown in Figure 19-2 below:
Figure 19-2
19.4 Foundation and Material composables
When developing apps with Compose we do so using a mixture of our own composable functions (for example
the CustomText and CustomList composables created earlier in the chapter) combined with a set of ready
to use components provided by the Compose development kit (such as the Text, Button, Column and Slider
composables).
The composables bundled with Compose fall into three categories, referred to as Layout, Foundation, and
Material Design components.
Layout components provide a way to define both how components are positioned on the screen, and how those
components behave in relation to each other. The following are all layout composables:
• Box
• BoxWithConstraints
• Column
• ConstraintLayout
• Row
Foundation components are a set of minimal components that provide basic user interface functionality. While
these components do not, by default, impose a specific style or theme, they can be customized to provide any
look and behavior you need for your app. The following lists the set of Foundation components:
• BaseTextField
• Canvas
• Image
• LazyColumn
• LazyRow
154
Composable Functions Overview
• Shape
• Text
The Material Design components, on the other hand, have been designed so that they match Google’s Material
theme guidelines and include the following composables:
• AlertDialog
• Button
• Card
• CircularProgressIndicator
• DropdownMenu
• Checkbox
• FloatingActionButton
• LinearProgressIndicator
• ModalDrawer
• RadioButton
• Scaffold
• Slider
• Snackbar
• Switch
• TextField
• TopAppBar
• BottomNavigation
When choosing components, it is important to note that the Foundation and Material Design components
are not mutually exclusive. You will inevitably use components from both categories in your design since the
Material Design category has components for which there is no Foundation equivalent and vice versa.
19.5 Summary
In this chapter, we have looked at composable functions and explored how they are used to construct Android-
based user interfaces. Composable functions are declared using the @Composable annotation and use the same
syntax as standard Kotlin functions, including the passing and handling of parameters. Unlike standard Kotlin
functions, composable functions do not return values. Instead, they emit user interface units to be rendered
by the Compose runtime. A composable function can be either stateful or stateless depending on whether the
function stores a state value. The built-in composables are categorized as either Layout, Foundation, or Material
Design components. The Material Design components conform with the Material style and theme guidelines
provided by Google to encourage consistent UI design.
One type of composable we have not yet introduced is the Slot API composable, a topic that will be covered later
in the chapter entitled “An Overview of Compose Slot APIs”.
155