Exploring BasicText and Text in Compose

When it comes to displaying text, Compose offers two composables, Text and BasicText, for high-level and low-level text rendering, respectively.

Exploring BasicText in Compose

BasicText is a barebones composable that offers low-level text rendering ability and semantics/accessibility information with limited options. Here’s what its signature looks like:

@Composable
fun BasicText(
  text: String,
  modifier: Modifier = Modifier,
  style: TextStyle = TextStyle.Default,
  onTextLayout: ((TextLayoutResult) -> Unit)? = null,
  overflow: TextOverflow = TextOverflow.Clip,
  softWrap: Boolean = true,
  maxLines: Int = Int.MAX_VALUE,
  minLines: Int = 1,
  color: ColorProducer? = null
)

BasicText has the following input parameters:

  • text: The text to be displayed.
  • modifier: The modifier to be applied to this layout.
  • style: The style configuration for the text layout.
  • onTextLayout: Callback that is executed when a new text layout is calculated.
  • overflow: Determines how overflow should be handled in the text.
  • softWrap: Determines whether the text should break at soft line breaks.
  • maxLines: Number of lines the text will span.
  • minLines: Minimum number of lines the text will occupy.
  • color: The color of the text, which overrides the value provided in the style.

In most cases, you’ll rely on the Text composable instead. It offers more customization options, as you’ll see later in this lesson, but it also provides handy abstractions that do the heavy lifting for you.

If Text composable is the way to go for most scenarios, why does the BasicText composable exist?

There are cases where you’ll need customization in the drawing logic for your text or when you need to perform additional tasks after the text is rendered, you need to use BasicText, as it offers more control over the drawing of the text.

Also, when it comes to performance, BasicText can be more performant in scenarios where the advanced features of Text are unnecessary. It’s lighter and more suitable for cases requiring minimal text rendering.

Exploring Text in Compose

Before learning how to use the Text Composable, you’ll examine its signature and see how much it differs from BasicText.

@Composable
fun Text(
  text: String,
  modifier: Modifier = Modifier,
  color: Color = Color.Unspecified,
  fontSize: TextUnit = TextUnit.Unspecified,
  fontStyle: FontStyle? = null,
  fontWeight: FontWeight? = null,
  fontFamily: FontFamily? = null,
  letterSpacing: TextUnit = TextUnit.Unspecified,
  textDecoration: TextDecoration? = null,
  textAlign: TextAlign? = null,
  lineHeight: TextUnit = TextUnit.Unspecified,
  overflow: TextOverflow = TextOverflow.Clip,
  softWrap: Boolean = true,
  maxLines: Int = Int.MAX_VALUE,
  minLines: Int = 1,
  onTextLayout: ((TextLayoutResult) -> Unit)? = null,
  style: TextStyle = LocalTextStyle.current
)

Immediately, you’ll notice far more customization options in Text. Go over these options one by one:

  • text: The text to be displayed.
  • modifier: The modifier to be applied to this layout.
  • color: The color to be applied to the text.
  • fontSize: The size of glyphs to use when painting the text.
  • fontStyle: The typeface to use when drawing the letters (e.g., italic).
  • fontWeight: The thickness to use when painting the text (e.g., FontWeight.Bold).
  • fontFamily: The font family to be used when rendering the text.
  • letterSpacing: The amount of space to add between each letter.
  • textDecoration: The decorations to paint on the text (e.g., an underline).
  • textAlign: The alignment of the text within the paragraph.
  • lineHeight: Line height for the Paragraph in TextUnit unit, e.g., SP or EM. See TextStyle.lineHeight.
  • overflow: How visual overflow should be handled.
  • softWrap: Whether the text should break at soft line breaks.
  • maxLines: Number of lines the text will span.
  • minLines: Minimum number of lines the text will occupy.
  • onTextLayout: Callback that is executed when a new text layout is calculated.
  • style: Style configuration for the text, such as color, font, line height etc.

Text is extremely feature-rich and flexible, and integrates seamlessly with Material Design.

Now that you’ve looked at both Text and BasicText, and each of their offerings, it’s now time to see how you can use text in Compose.

Using Text

The simplest way to display text in compose is by using the Text composable and passing a string as a parameter.

@Composable
fun HelloCompose() {
  Text("Hello Compose")
}

But it’s recommended not to hardcode your text values and use string resources instead. Here’s what that looks like in compose:

@Composable
fun HelloCompose() {
  Text(stringResource(R.string.hello_compose))
}

You can also use an annotated string in case you want to style only part of your text and leave the rest untouched:

@Composable
fun StyledText() {
  val annotatedString = buildAnnotatedString {
    append("This is ")
    withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
      append("bold text")
    }
    append(" and this is not.")
  }

  Text(text = annotatedString)
}

Now that you’ve covered the basics of displaying text with compose, it’s time to look at how to style your text to match your brand better.

Styling Text

Some common options to style your text would be to change the color, font size, and font weight.

You can achieve these as follows:

@Composable
fun RedBoldBigText() {
  Text(
    text = "Hello World",
    color = Color.Red,
    fontSize = 30.sp,
    fontWeight = FontWeight.Bold
  )
}

The snippet above renders the text “Hello World” in red color, with a bold weight, and a font size of 30sp.

With these basic customizations out of the way, take a look at some of the more advanced tweaks you can make.

Skewing Your Text

To skew your text, you can use the style property along with a textGeometricTransform as shown below.

@Composable
fun SlantedText() {
  Text(
    modifier = Modifier.width(150.dp),
    textAlign = TextAlign.Center,
    text = "Slanted",
    color = Color.Blue,
    fontSize = 30.sp,
    style = TextStyle(
      textGeometricTransform = TextGeometricTransform(
        scaleX = 0.5f,
        skewX = 1.3f
      )
    ),
    fontWeight = FontWeight.Bold
  )
}

The snippet above creates a Text composable with

  • A width of 150dp.
  • Text alignment of TextAlign.Center.
  • Text color of blue.
  • A font size of 30sp.
  • A text style that uses a geometric transform to scale down the text to half its horizontal size and skew it horizontally with a shear of 1.3f.
  • A bold font weight.

The resulting text looks as follows:

Adding Shadow to Your Text

The style parameter of the text composable lets you configure multiple parameters, such as shadow.

Shadow receives a color for the shadow, the offset, or its position with respect to the Text and the blur radius, which is how blurry it looks.

@Composable
fun ShadowText() {
  val offset = Offset(5.0f, 10.0f)
  Text(
    text = "I got shadows!",
    style = TextStyle(
      fontSize = 24.sp,
      shadow = Shadow(
        color = Color.Gray, offset = offset, blurRadius = 3f
      )
    )
  )
}

In the snippet above, the offset defines the position where the shadow will be drawn. When defining the shadow, you also declare the blur radius, which defines how much the shadow will spread beneath the text.

The resulting appearance of the above is shown in the screenshot below:

Using Gradient as Text Color

Using the style parameter, you can also opt for using a gradient as the text color. Here’s what using a gradient as the text color looks like:

@Composable
fun GradientText() {
  val gradientColors = listOf(Color.Cyan, Color.Magenta, Color.Red)

  Text(
    text = "Here's a text with a gradient color!",
    style = TextStyle(
      brush = Brush.linearGradient(
        colors = gradientColors
      )
    )
  )
}

In the snippet above, you declared the gradient colors in a list. After this, you defined a brush using the Brush.linearGradient to use the colors to render a gradient as the text color.

The final appearance looks as follows:

Styling Paragraphs

Now that you’ve covered how to style individual blocks of text, it’s time to look at how to style paragraphs.

Compose offers a ParagraphStyle that lets you style individual chunks of the text with different styles. This is convenient when you want to emphasize a certain part of the text with one style while keeping the rest in another.

@Composable
fun ParagraphStylingExample() {
  Text(
    buildAnnotatedString {
      withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
        withStyle(
          style = SpanStyle(
            color = Color.Blue, shadow = Shadow(
              color = Color.Gray,
              offset = Offset(5.0f, 10.0f),
              blurRadius = 3f
            )
          )
        ) {
          append(
            "This paragraph has a shadow under it. Looks funky\n"
          )
        }
        withStyle(
          style = SpanStyle(
            fontWeight = FontWeight.Bold, color = Color.Red
          )
        ) {
          append("This paragraph is just bold.\n")
        }
        append("Finally here is an unstyled paragraph")
      }
    }
  )
}

The snippet above uses the buildAnnotatedString lambda to create an annotated string with the required styling. Within the lambda, the content of the paragraph is incrementally configured with its own unique styling using the withStyle function, which takes in a SpanStyle.

For each segment of the paragraph, the styling is defined as shown in previous sections of the lesson.

Finally, the output of buildAnnotatedString is passed on to the enclosing Text composable as the input.

The result is as follows:

See forum comments
Download course materials from Github
Previous: Introduction Next: Using Text Composable in App