Highlighting
About this widget
Displays the highlighted attributes of your search results.
With InstantSearch Android, the Highlightable
interface and HighlightedString
objects simplify highlighting the correct words in a search response that match your query.
Examples
Consider a movies index.
Each movie record consists of two fields: title
and year
.
Algolia’s response to the 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
Update it to add some highlighting. Implementing Highlightable
will deserialize the _highlightResult
for each movie, and make it available through the getHighlight{s}
methods. Create @Transient
attributes for each highlight 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"))
}
Use these highlighted strings in the interface, for example in a MovieViewHolder
. There are three ways you can use a HighlightedString
:
Using highlighted strings in an Android view
- Directly as a
SpannedString
, with the highlight defaulting to bold:Copy1
TextUtils.concat(highlightedTitle?.toSpannedString(), " ($year)")
- As a customized
SpannedString
, specifying aParcelableSpan
to use as highlight style:Copy1 2
highlightedGenres?.toSpannedString(BackgroundColorSpan(Color.YELLOW)) ?: buildSpannedString { italic { append("unknown genre") } }
- Any way you want, iterating on
HighlightedString#tokens
to 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.uppercase() else it.content } }
Compose UI
- Directly as a
AnnotatedString
, with the highlight defaulting to bold:Copy1
highlightedTitle?.toAnnotatedString()
- As a customized
AnnotatedString
, specifying aSpanStyle
to use as highlight style:Copy1 2
highlightedGenres?.toAnnotatedString(SpanStyle(background = Color.Yellow)) ?: AnnotatedString("unknown genre", SpanStyle(fontStyle = FontStyle.Italic))
- Any way you want, iterating on
HighlightedString#tokens
to 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.uppercase() else it.content } }