Annotated Text in Jetpack Compose

Kevin Skrei
2 min readOct 4, 2021

--

At Arccos Golf, we decided to upgrade our golf course search experience. This gave me a great opportunity to use Jetpack Compose in a low risk feature change. Our course search feature is pretty simple: you type in some text, we hit an API, and display a list of golf courses that match a search query. One of the interesting requirements from our designers was to display the golf course name differently depending on the search term. The designers wanted to show a different text style for the first occurrence of the search term in the course name. See the example below

Our design requirements specified that we should change the text style of the results if it contains the query.

Notice how “tam” is the search query and “tam” in all of the search results is a distinct, light gray text style. I was curious about how to accomplish this in Compose. I had seen something like this before with native views using annotated strings. I was hoping something similar would be available in Compose and I was right :)

Show me some code

One of the Text constructor overloads accepts an AnnotatedString parameter. This AnnotatedString allows you to construct a string with various styles placed at different character indices in the string. Let’s start with a simple data class that contains the search query and a golf course.

data class GolfCourse(val name : String) //Removed properties for brevitydata class CourseSearchViewModel(val searchQuery : String, course :  GolfCourse) {  //See getAnnotatedString definition below}

Step 1: Calculate the index of the search query in the title

Inside our CourseSearchViewModel we can make a function to get the AnnotatedString

fun getAnnotatedString(highlightStyle : SpanStyle) : AnnotatedString {
//Find where searchQuery appears in courseName
val startIndex = course.name.indexOf(searchQuery, 0, searchQuery.length)
val builder = AnnotatedString.Builder(course.name)
//If the query is in the name, add a style, otherwise do nothing
if(startIndex >= 0) {
val endIndex = startIndex + searchQuery.length
builder.addStyle(highlightStyle, startIndex, endIndex)
}
return builder.toAnnotatedString()
}

Now, you can call this function from your compose view.

@Composable
fun HighlightedText(model : CourseSearchViewModel) {
Text(model.getAnnotatedString(SpanStyle(color = Color.Red, fontWeight = FontWeight.Bold)),
color = Color.Black) //Default color for Text
}

Our styles are a little different but the above should give you default black text with the search query bolded in red. Here is an example of it in Arccos in our new search experience.

Example of search result with annotated string in Compose

There you have it. A simple, yet great way to improve your search experience! Check out the docs on how to style text: https://developer.android.com/jetpack/compose/text

--

--