Instruction

Exploring Built-in Components

Before looking at how you can clean up the GitHub repo app using components, it’s a good practice to explore some of the foundational components that Jetpack Compose ships with.

Learning how these components work will also help you in the future when you’re building a component catalog for your app or a design system since you won’t have to do a lot of heavy lifting or reinventing the wheel.

Like most things in programming, Compose also follows Pareto’s principle—20% of the components in Compose’s catalog will let you build 80% of all user interfaces.

Throughout this course, you’ve already covered basic components like Text and Button in the past modules. It’s worth expanding on that knowledge and covering a few more components, so you’ve got a working understanding of the fundamental pieces of the compose catalog.

Exploring the Image Component

You can use the Image component to display a graphic on your screen. To load an image from the disk (JPEG, PNG or WEBP), use the painterResource by passing the image reference as a parameter.

Here’s what that looks like:

Image(  
  painter = painterResource(id = R.drawable.ice_cream),  
  contentDescription = "Vanilla ice cream"  
)

In the snippet above you:

  • Used an Image component to render the ice_cream drawable.
  • You also supplied a content description for the image for accessibility.

Here’s what the Image component looks like internally:

@Composable  
fun Image(  
  painter: Painter,  
  contentDescription: String?,  
  modifier: Modifier = Modifier,  
  alignment: Alignment = Alignment.Center,  
  contentScale: ContentScale = ContentScale.Fit,  
  alpha: Float = DefaultAlpha,  
  colorFilter: ColorFilter? = null  
)

The Image component accepts quite a few parameters:

  • painter - The image content to be drawn.
  • contentDescription - Optional text label used by accessibility services to describe the image.
  • modifier - The modifier to customize the appearance and layout.
  • alignment - To control the image’s alignment within its parent’s bounds.
  • contentScale - To control the aspect ratio of the image.
  • alpha - Opacity applied to the image.
  • colorFilter - Optional parameter to control the color of the individual pixels of the drawn image.

Note: While contentDescription is optional, it’s recommended to supply a value for the field to ensure your app works well for users who use screen readers or other accessibility services.

Displaying Vector Images

VectorDrawables is the standard API used when you want to display a vector asset in your app. These vectors are usually icons.

Unlike PNG, JPEG or WEBP formats, referred to as raster graphic formats, that are made up of pixels, vectors are infinitely scalable without any loss in fidelity as they use mathematical path representations with drawing instructions instead of pixels.

In compose, when you want to show a vector asset on the screen, you use the same Image component and supply the vector reference to painterResource, like shown below:

Image(  
  painter = painterResource(id = R.drawable.ic_add),  
  contentDescription = "Add button"  
)

For you, the API surface stays the same, and compose abstracts away the drawing logic across different image categories.

Currently, painterResource supports the following drawable types:

  • AnimatedVectorDrawable
  • BitmapDrawable
  • VectorDrawable
  • ColorDrawable

Exploring Buttons

You’ve already covered buttons a few times in the previous lessons, but it’s time you covered all the different types of buttons compose offers and where you should use them.

Compose has five categories of buttons:

  • Filled
  • Filled tonal
  • Elevated
  • Outlined
  • Text

These five varieties of buttons serve different use cases, which you’ll learn about shortly.

Under the hood, all these five variants have a similar API surface. They accept

  • onClick - A function that is triggered when the button is clicked.
  • enabled - A flag to control whether the button is enabled or disabled.
  • colors - An instance of ButtonColors that control the button’s colors in different states.
  • contentPadding - Padding within the button.

Filled Button

A filled button is the basic Button component that you’ve used so far. It’s filled with a solid color by default. Following is a simple example of a filled button:

@Composable  
fun FilledButtonExample() {  
  Button(onClick = { onClick() }) {  
    Text("Filled button")  
  }
}

Here’s what a filled button from the snippet above looks like:

Filled Tonal Button

A filled tonal button is filled with a tonal color based on the material design spec by default. The following snippet shows an example of the FilledTonalButton component:

@Composable  
fun FilledTonalButtonExample() {  
  FilledTonalButton(onClick = { onClick() }) {  
    Text("Filled tonal button")  
  }  
}

The snippet above results in the following UI:

Elevated Button

An elevated button has a shadow that represents the elevation effect by default. It’s an outlined button with a default shadow. Here’s an example of how the ElevatedButton component is used:

@Composable  
fun ElevatedButtonExample() {  
  ElevatedButton(onClick = { onClick() }) {  
    Text("Elevated button")  
  }  
}

The snippet above results in the following UI.

Outlined Button

An outlined button has no color fill but comes with an outline by default. Here’s an example of the same:

@Composable  
fun OutlinedButtonExample() {  
  OutlinedButton(onClick = { onClick() }) {  
    Text("Outlined button")  
  }  
}

Here’s what an outlined button from the snippet above looks like:

Text Button

Finally, the text button component appears only as text. By default, it has no fill, outline or elevation. However, it still has the necessary interaction indicators to differentiate it from a text component with a clickable modifier.

Here’s an example of the TextButton component:

@Composable  
fun TextButtonExample() {  
  TextButton(onClick = { onClick() }) {  
    Text("Text button")  
  }  
}

Here’s what the text button from the snippet above looks like:

Exploring the Switch Component

The Switch component allows users to toggle between a checked and unchecked state. You can use the switch to let users:

  • Enable/disable a feature.
  • Toggle a feature.
  • Turn a setting on or off.

Take a look at the signature of the Switch component:

@Composable  
fun Switch(  
  checked: Boolean,  
  onCheckedChange: ((Boolean) -> Unit)?,  
  modifier: Modifier = Modifier,  
  thumbContent: (@Composable () -> Unit)? = null,  
  enabled: Boolean = true,  
  colors: SwitchColors = SwitchDefaults.colors(),  
  interactionSource: MutableInteractionSource = remember { 
    MutableInteractionSource() 
  },  
)

The component accepts the following parameters:

  • checked - Determines whether the switch is in the checked or unchecked state.
  • onCheckedChange - The function to be triggered when the state of the switch changes.
  • modifier - Modifier to be applied to the switch.
  • thumbContent - Content to be drawn on the thumb of the switch.
  • enabled - To control whether the switch is enabled or disabled for interaction.
  • colors - Colors to be used for the switch in different states.
  • interactionSource - The interaction source representing the stream of interactions for this switch.

Here’s a simple example of using the switch component:

@Composable  
fun SwitchExample() {  
  var checked by remember { mutableStateOf(true) }  
  Switch(  
    checked = checked,  
    onCheckedChange = {  
      checked = it  
    })  
}

And this is what the resulting switch will look like:

See forum comments
Download course materials from Github
Previous: Introduction Next: Demo