{% setvar book_path %}/reference/androidx/_book.yaml{% endsetvar %} {% include "_shared/_reference-head-tags.html" %}

TextPainterKt

public final class TextPainterKt


Summary

Public methods

static final void
drawText(
    @NonNull DrawScope receiver,
    @NonNull TextLayoutResult textLayoutResult,
    @NonNull Brush brush,
    @NonNull Offset topLeft,
    float alpha,
    Shadow shadow,
    TextDecoration textDecoration,
    DrawStyle drawStyle,
    @NonNull BlendMode blendMode
)

Draw an existing text layout as produced by TextMeasurer.

static final void
drawText(
    @NonNull DrawScope receiver,
    @NonNull TextLayoutResult textLayoutResult,
    @NonNull Color color,
    @NonNull Offset topLeft,
    float alpha,
    Shadow shadow,
    TextDecoration textDecoration,
    DrawStyle drawStyle,
    @NonNull BlendMode blendMode
)

Draw an existing text layout as produced by TextMeasurer.

static final void
drawText(
    @NonNull DrawScope receiver,
    @NonNull TextMeasurer textMeasurer,
    @NonNull String text,
    @NonNull Offset topLeft,
    @NonNull TextStyle style,
    @NonNull TextOverflow overflow,
    boolean softWrap,
    int maxLines,
    @NonNull Size size,
    @NonNull BlendMode blendMode
)

Draw text using a TextMeasurer.

static final void
drawText(
    @NonNull DrawScope receiver,
    @NonNull TextMeasurer textMeasurer,
    @NonNull AnnotatedString text,
    @NonNull Offset topLeft,
    @NonNull TextStyle style,
    @NonNull TextOverflow overflow,
    boolean softWrap,
    int maxLines,
    @NonNull List<@NonNull AnnotatedString.Range<@NonNull Placeholder>> placeholders,
    @NonNull Size size,
    @NonNull BlendMode blendMode
)

Draw styled text using a TextMeasurer.

Public methods

drawText

public static final void drawText(
    @NonNull DrawScope receiver,
    @NonNull TextLayoutResult textLayoutResult,
    @NonNull Brush brush,
    @NonNull Offset topLeft,
    float alpha,
    Shadow shadow,
    TextDecoration textDecoration,
    DrawStyle drawStyle,
    @NonNull BlendMode blendMode
)

Draw an existing text layout as produced by TextMeasurer.

This draw function cannot relayout when async font loading resolves. If using async fonts or other dynamic text layout, you are responsible for invalidating layout on changes.

Parameters
@NonNull TextLayoutResult textLayoutResult

Text Layout to be drawn

@NonNull Brush brush

The brush to use when drawing the text.

@NonNull Offset topLeft

Offsets the text from top left point of the current coordinate system.

float alpha

Opacity to be applied to brush from 0.0f to 1.0f representing fully transparent to fully opaque respectively.

Shadow shadow

The shadow effect applied on the text.

TextDecoration textDecoration

The decorations to paint on the text (e.g., an underline).

DrawStyle drawStyle

Whether or not the text is stroked or filled in.

@NonNull BlendMode blendMode

Blending algorithm to be applied to the text

drawText

public static final void drawText(
    @NonNull DrawScope receiver,
    @NonNull TextLayoutResult textLayoutResult,
    @NonNull Color color,
    @NonNull Offset topLeft,
    float alpha,
    Shadow shadow,
    TextDecoration textDecoration,
    DrawStyle drawStyle,
    @NonNull BlendMode blendMode
)

Draw an existing text layout as produced by TextMeasurer.

This draw function cannot relayout when async font loading resolves. If using async fonts or other dynamic text layout, you are responsible for invalidating layout on changes.

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layout
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.sp

val textMeasurer = rememberTextMeasurer()
var textLayoutResult by remember {
    mutableStateOf<TextLayoutResult?>(null)
}

Canvas(
    Modifier
        .fillMaxSize()
        .layout { measurable, constraints ->
            val placeable = measurable.measure(constraints)
            // TextLayout can be done any time prior to its use in draw, including in a
            // background thread.
            // In this sample, text layout is measured in layout modifier. This way the layout
            // call can be restarted when async font loading completes due to the fact that
            // `.measure` call is executed in `.layout`.
            textLayoutResult = textMeasurer.measure(
                text = "Hello, World!",
                style = TextStyle(fontSize = 24.sp)
            )
            layout(placeable.width, placeable.height) {
                placeable.placeRelative(0, 0)
            }
        }) {
    // This happens during draw phase.
    textLayoutResult?.let { drawText(it) }
}
import androidx.compose.animation.animateColor
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.LocalTextStyle
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layout
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Constraints

// We can disable implicit caching since we will cache in DrawWithCache
val textMeasurer = rememberTextMeasurer(cacheSize = 0)
// Apply the current text style from theme, otherwise TextStyle.Default will be used.
val materialTextStyle = LocalTextStyle.current

// Animate color repeatedly
val infiniteTransition = rememberInfiniteTransition()
val color by infiniteTransition.animateColor(
    initialValue = Color.Red,
    targetValue = Color.Blue,
    animationSpec = infiniteRepeatable(tween(1000))
)

Box(
    Modifier
        .fillMaxSize()
        .drawWithCache {
            // Text layout will be measured just once until the size of the drawing area or
            // materialTextStyle changes.
            val textLayoutResult = textMeasurer.measure(
                text = "Hello, World!",
                style = materialTextStyle,
                constraints = Constraints.fixed(
                    width = (size.width / 2).roundToInt(),
                    height = (size.height / 2).roundToInt()
                ),
                overflow = TextOverflow.Ellipsis
            )
            // color changes will only invalidate draw phase
            onDrawWithContent {
                drawContent()
                drawText(
                    textLayoutResult,
                    color = color,
                    topLeft = Offset(
                        (size.width - textLayoutResult.size.width) / 2,
                        (size.height - textLayoutResult.size.height) / 2,
                    )
                )
            }
        })
Parameters
@NonNull TextLayoutResult textLayoutResult

Text Layout to be drawn

@NonNull Color color

Text color to use

@NonNull Offset topLeft

Offsets the text from top left point of the current coordinate system.

float alpha

opacity to be applied to the color from 0.0f to 1.0f representing fully transparent to fully opaque respectively

Shadow shadow

The shadow effect applied on the text.

TextDecoration textDecoration

The decorations to paint on the text (e.g., an underline).

DrawStyle drawStyle

Whether or not the text is stroked or filled in.

@NonNull BlendMode blendMode

Blending algorithm to be applied to the text

drawText

public static final void drawText(
    @NonNull DrawScope receiver,
    @NonNull TextMeasurer textMeasurer,
    @NonNull String text,
    @NonNull Offset topLeft,
    @NonNull TextStyle style,
    @NonNull TextOverflow overflow,
    boolean softWrap,
    int maxLines,
    @NonNull Size size,
    @NonNull BlendMode blendMode
)

Draw text using a TextMeasurer.

This draw function supports only one text style, and async font loading.

TextMeasurer carries an internal cache to optimize text layout measurement for repeated calls in draw phase. If layout affecting attributes like font size, font weight, overflow, softWrap, etc. are changed in consecutive calls to this method, TextMeasurer and its internal cache that holds layout results may not offer any benefits. Check out TextMeasurer and drawText overloads that take TextLayoutResult to learn more about text layout and draw phase optimizations.

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer

val textMeasurer = rememberTextMeasurer()

Canvas(Modifier.fillMaxSize()) {
    drawText(textMeasurer, "Hello, World!")
}
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.sp

val textMeasurer = rememberTextMeasurer()

Canvas(Modifier.fillMaxSize()) {
    drawText(
        textMeasurer = textMeasurer,
        text = "Hello, World!",
        style = TextStyle(
            fontSize = 24.sp,
            fontWeight = FontWeight.Bold,
            textDecoration = TextDecoration.Underline
        )
    )
}
Parameters
@NonNull TextMeasurer textMeasurer

Measures and lays out the text

@NonNull String text

Text to be drawn

@NonNull Offset topLeft

Offsets the text from top left point of the current coordinate system.

@NonNull TextStyle style

the TextStyle to be applied to the text

@NonNull TextOverflow overflow

How visual overflow should be handled.

boolean softWrap

Whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If softWrap is false, overflow and TextAlign may have unexpected effects.

int maxLines

An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to overflow and softWrap. If it is not null, then it must be greater than zero.

@NonNull Size size

how wide and tall the text should be. If left Size.Unspecified as its default value, text will be forced to fit inside the total drawing area from where it's placed. If size is specified, Size.width will define the width of the text. Size.height helps defining the number of lines that fit if softWrap is enabled and overflow is TextOverflow.Ellipsis. Otherwise, Size.height either defines where the text is clipped (TextOverflow.Clip) or becomes no-op.

@NonNull BlendMode blendMode

Blending algorithm to be applied to the text

drawText

public static final void drawText(
    @NonNull DrawScope receiver,
    @NonNull TextMeasurer textMeasurer,
    @NonNull AnnotatedString text,
    @NonNull Offset topLeft,
    @NonNull TextStyle style,
    @NonNull TextOverflow overflow,
    boolean softWrap,
    int maxLines,
    @NonNull List<@NonNull AnnotatedString.Range<@NonNull Placeholder>> placeholders,
    @NonNull Size size,
    @NonNull BlendMode blendMode
)

Draw styled text using a TextMeasurer.

This draw function supports multi-styling and async font loading.

TextMeasurer carries an internal cache to optimize text layout measurement for repeated calls in draw phase. If layout affecting attributes like font size, font weight, overflow, softWrap, etc. are changed in consecutive calls to this method, TextMeasurer and its internal cache that holds layout results may not offer any benefits. Check out TextMeasurer and drawText overloads that take TextLayoutResult to learn more about text layout and draw phase optimizations.

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.ParagraphStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle

val textMeasurer = rememberTextMeasurer()

Canvas(Modifier.fillMaxSize()) {
    drawText(
        textMeasurer = textMeasurer,
        text = buildAnnotatedString {
            withStyle(ParagraphStyle(textAlign = TextAlign.Start)) {
                append("Hello")
            }
            withStyle(ParagraphStyle(textAlign = TextAlign.End)) {
                append("World")
            }
        }
    )
}
Parameters
@NonNull TextMeasurer textMeasurer

Measures and lays out the text

@NonNull AnnotatedString text

Text to be drawn

@NonNull Offset topLeft

Offsets the text from top left point of the current coordinate system.

@NonNull TextStyle style

the TextStyle to be applied to the text

@NonNull TextOverflow overflow

How visual overflow should be handled.

boolean softWrap

Whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If softWrap is false, overflow and TextAlign may have unexpected effects.

int maxLines

An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to overflow and softWrap. If it is not null, then it must be greater than zero.

@NonNull List<@NonNull AnnotatedString.Range<@NonNull Placeholder>> placeholders

a list of Placeholders that specify ranges of text which will be skipped during layout and replaced with Placeholder. It's required that the range of each Placeholder doesn't cross paragraph boundary, otherwise IllegalArgumentException is thrown.

@NonNull Size size

how wide and tall the text should be. If left Size.Unspecified as its default value, text will be forced to fit inside the total drawing area from where it's placed. If size is specified, Size.width will define the width of the text. Size.height helps defining the number of lines that fit if softWrap is enabled and overflow is TextOverflow.Ellipsis. Otherwise, Size.height either defines where the text is clipped (TextOverflow.Clip) or becomes no-op.

@NonNull BlendMode blendMode

Blending algorithm to be applied to the text