8

As we know, AnnotatedString in JetpackCompose has provided some API of Android's SpannedString.

but I didn't find any way/workaround to inline ImageSpan to a Text (except using AndroidView)

beigirad
  • 4,986
  • 2
  • 29
  • 52

1 Answers1

31

Putting images inside text can be done using AnnotatedString and inlineContent parameter of Text Composable.

  • Inside buildAnnotatedString { ... } we need to define some id for our inline content using appendInlineContent(id = ...)
  • Then in Text Composable in inlineContent parameter we provide a map matching this id to InlineTextContent() object.

You can basically put any content there as long as you can define its size up-front in Placeholder.

Here is how it looks with an Image put in the middle of the text: enter image description here

val annotatedString = buildAnnotatedString {
    append("This is text ")
    appendInlineContent(id = "imageId")
    append(" with a call icon")
}
val inlineContentMap = mapOf(
    "imageId" to InlineTextContent(
        Placeholder(20.sp, 20.sp, PlaceholderVerticalAlign.TextCenter)
    ) {
        Image(
            imageVector = Icons.Default.Call,
            modifier = Modifier.fillMaxSize(),
            contentDescription = ""
        )
    }
)

Text(annotatedString, inlineContent = inlineContentMap)
Maciej Ciemięga
  • 10,125
  • 1
  • 41
  • 48
  • 2
    There's an interesting caveat here, that you have to know the size of the content up-front. In my case, I can only figure it out by spending the time to render the image up-front, which kind of sucks. I wonder what happens if I just put the wrong size in... – Hakanai Mar 15 '22 at 05:56
  • 3
    you should put `inlineContentMap` in a remember – mr.icetea May 20 '22 at 04:42
  • 1
    @mr.icetea `remember` doesn't allow while message is being appended using `stringResource(resId)`. – Rahul Rastogi Sep 20 '22 at 15:16