Highlighting
About this widget
A great search interface highlights parts of the search results to explain why they are relevant to the user.
With InstantSearch Android, the Highlightable interface and HighlightedString objects simplify highlighting the right words in a search response that match your query.
You can read more about the concept of highlighting in our highlighting guide.
Examples
Lets take the example of an index containing movies. Each movie record consists of two fields: title and year.
Here is what the search engine response for a query "red" could look like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"title": "The Shawshank Redemption",
"year": 1994,
"genre": ["action", "adventure"],
"actors": ["Tim Robbins", "Morgan Freeman"],
"objectID": "439817390",
"_highlightResult": {
"title": {
"value": "The Shawshank <em>Red</em>emption",
"matchLevel": "full",
"fullyHighlighted": false,
"matchedWords": [
"red"
]
},
}
},
To display those movies in your interface, you likely have created a data class that looks something like the following:
1
2
3
4
5
6
7
@Serializable
data class Movie(
val title: String,
val year: String,
val genre: List<String>,
override val objectID: ObjectID,
) : Indexable
Let’s update it to add some highlighting. Implementing Highlightable will deserialize the _highlightResult for each movie, and make it available through the getHighlight{s} methods. We can then create @Transient attributes for each highlight we want to display, being either single values or lists:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Serializable
data class Movie(
val title: String,
val year: String,
val genre: List<String>,
override val objectID: ObjectID
override val _highlightResult: JsonObject?
) : Indexable, Highlightable {
@Transient
public val highlightedTitle: HighlightedString?
get() = getHighlight(Attribute("title"))
@Transient
public val highlightedGenres: List<HighlightedString>?
get() = getHighlights(Attribute("genre"))
@Transient
public val highlightedActors: List<HighlightedString>?
get() = getHighlights(Attribute("actors"))
}
We can now use these highlighted strings in our interface, for example in a MovieViewHolder. There are three ways you can use a HighlightedString:
- Directly as a
SpannedString, with the highlight defaulting to bold:Copy1
TextUtils.concat(highlightedTitle?.toSpannedString(), " ($year)")
- As a customized
SpannedString, specifying aParcelableSpanto use as highlight style:Copy1 2
highlightedGenres?.toSpannedString(BackgroundColorSpan(Color.YELLOW)) ?: buildSpannedString { italic { append("unknown genre") } }
- Any way you want, iterating on
HighlightedString#tokensto process it however you like:Copy1 2 3 4 5 6
// Displays actors with highlighted parts in uppercase highlightedActors?.joinToString { highlight -> highlight.tokens.joinToString("") { if (it.highlighted) it.content.toUpperCase() else it.content } }