Highlight filtered Text in Compose While Using Search

Kamaldeep Kumar
2 min readJan 22, 2022

--

Jetpack Compose is a modern declarative UI Toolkit for Android. The best way to learn any new technology is to build something.

There is one kind of requirement Highlight filtered Text from List when we are using search. This artical is about to solve this problem in Compose.

Now, we will take an example of Dog Breed List where user can search dog breed and highlighted matching name from list.

we will go for the following steps in order to achieve desired results…

  1. Make a search view
  2. Use LazyList to show Dog list
  3. Get substring list which matches with the Search Text
  4. Display of highlighted text

Compose Components used for this requirement are: TextField, LazyColumn, buildAnnotatedString

1. Make a Search View

@Composable
fun SearchView(
searchText: String,
onSearchTextChange: (String) -> Unit
) {
TextField(
value = searchText,
onValueChange = onSearchTextChange,
trailingIcon = {
Icon(Icons.Default.Search, contentDescription = "")
},
label = { Text(text = "Search here ...") },
singleLine = true,
modifier = Modifier.fillMaxWidth()
)
}

We create SearchView using TextField where user can enter text.

2. Use LazyList to show Dog list

@Composable
fun ListDataView(
searchText: String,
dogList: List<DogModel>
) {
LazyColumn {
itemsIndexed(dogList) { _, item ->
DogItemCard(searchText = searchText, itemName = item)
}
}
}

With the help of LazyColumn we create vertical list which shows Dog list

3. Get substring list which matches with the Search Text

private fun getSubStrings(subString: String, text: String): List<IntRange> {
return subString.toRegex()
.findAll(text)
.map { it.range }
.toList()
}

this function is returning the list with range which matches with search text. Now, we move to last step to highlight the text.

4. Display of highlighted text

@Composable
fun DogItemCard(searchText: String, itemName: DogModel) {
val subStrings = getSubStrings(searchText.lowercase(), itemName.name.lowercase())
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp),
elevation = 2.dp,
backgroundColor = Color.White,
shape = Shapes.small
) {
Text(
text = buildAnnotatedString {
append(itemName.name)
addStyle(
style = SpanStyle(
color = if (searchText.isNotEmpty()) Color.LightGray else Color.DarkGray
),
start = 0,
end = itemName.name.length
)
if (searchText.isNotEmpty()) {
for (subStringRange in subStrings) {
addStyle(
style = SpanStyle(Color.Black),
start = subStringRange.first,
end = subStringRange.last + 1
)
}
}

},
modifier = Modifier.padding(6.dp)
)
}
}

here we used buildAnnotatedString{} to achive this.

Photo by Alex Guillaume on Unsplash

git code link: https://github.com/kamydeep00178/ComposeSearch

for more info about buildAnnotatedString{} check the link below

https://developer.android.com/reference/kotlin/androidx/compose/ui/text/ParagraphStyle

--

--