UI libraries / InstantSearch Android / Widgets

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:
    1
    
    TextUtils.concat(highlightedTitle?.toSpannedString(), " ($year)")
    
  • As a customized SpannedString, specifying a ParcelableSpan to use as highlight style:
    1
    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:
    1
    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:
    1
    
      highlightedTitle?.toAnnotatedString()
    
  • As a customized AnnotatedString, specifying a SpanStyle to use as highlight style:
    1
    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:
    1
    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
          }
      }
    
Did you find this page helpful?