Skip to content

Instantly share code, notes, and snippets.

@micHar
Last active May 12, 2023 10:33
Show Gist options
  • Save micHar/99d8da443bfb9fc2e92a61ebaaacba72 to your computer and use it in GitHub Desktop.
Save micHar/99d8da443bfb9fc2e92a61ebaaacba72 to your computer and use it in GitHub Desktop.
Helper function loading annotated strings from strings.xml (might require further optimization)
import android.text.Annotation
import android.text.SpannedString
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.core.text.getSpans
@Composable
fun annotatedStringResource(
@StringRes id: Int,
spanStyles: (Annotation) -> SpanStyle? = { null }
): AnnotatedString {
val resources = LocalContext.current.resources
val spannedString = SpannedString(resources.getText(id))
val resultBuilder = AnnotatedString.Builder()
resultBuilder.append(spannedString.toString())
spannedString.getSpans<Annotation>(0, spannedString.length).forEach { annotation ->
val spanStart = spannedString.getSpanStart(annotation)
val spanEnd = spannedString.getSpanEnd(annotation)
resultBuilder.addStringAnnotation(
tag = annotation.key,
annotation = annotation.value,
start = spanStart,
end = spanEnd
)
spanStyles(annotation)?.let { resultBuilder.addStyle(it, spanStart, spanEnd) }
}
return resultBuilder.toAnnotatedString()
}
@micHar
Copy link
Author

micHar commented Nov 10, 2021

Usage:

<string name="someAnnotatedString">Some <annotation url="https://google.pl">link with "url" as key</annotation</string>

spanStyle sets up optional styling based on annotation.

    val someAnnotatedString = annotatedStringResource(
        id = R.string.someAnnotatedString,
        spanStyles = { annotation ->
            when (annotation.key) {
               "url" -> SpanStyle(textDecoration = TextDecoration.Underline)
                else -> null
            }
        }
    )

And AnnotatedString.getStringAnnotations are implicitly provided to e.g. provide clickable behavior.

            ClickableText(
                text = someAnnotatedString,
                ...
                onClick = { offset ->
                    someAnnotatedString.getStringAnnotations(tag = "url", start = offset, end = offset)
                        .firstOrNull()
                        ?.let { onOpenUrl(it.item) }
                }
            )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment