UI libraries / InstantSearch Android / Widgets
Signature
FilterListConnector.Numeric(
    filters: List<Filter.Numeric>,
    filterState: FilterState,
    selectionMode: SelectionMode,
    groupID: FilterGroupID
)

About this widget

FilterList.Numeric is a filtering view that displays any kind of numeric filters and lets users refine the search results by selecting them.

Compared to the RefinementList, which takes its values from the search response facets, this widget displays numeric filters that you add yourself.

Examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val filterState = FilterState()
    val price = Attribute("price")
    val groupColor = groupAnd(price)
    val numericFilters = listOf(
        Filter.Numeric(price, NumericOperator.Less, 5),
        Filter.Numeric(price, 5..10),
        Filter.Numeric(price, 10..25),
        Filter.Numeric(price, 25..100),
        Filter.Numeric(price, NumericOperator.Greater, 100)
    )
    val filterListConnector = FilterListConnector.Numeric(
        filters = numericFilters,
        filterState = filterState,
        groupID = groupColor
    )
    val connection = ConnectionHandler(filterListConnector, searcher.connectFilterState(filterState))

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val filterListView: FilterListView.Numeric = MyFilterListNumericAdapter() // your `FilterListView.Numeric` implementation
        connection += filterListConnector.connectView(filterListView)
        searcher.searchAsync()
    }

    override fun onDestroy() {
        super.onDestroy()
        connection.disconnect()
        searcher.cancel()
    }
}

Low-level API

If you want to fully control the FilterList.Numeric components and connect them manually, use the following components:

  • Searcher: The Searcher that handles your searches.
  • FilterState: The current state of the filters.
  • FilterListViewModel.Numeric: The logic applied to the numeric filters.
  • FilterListView.Numeric: The view that renders the numeric filters.
  • FilterPresenter: Optional. The presenter to customize the display of the filters.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val filterState = FilterState()
    val price = Attribute("price")
    val filters = listOf(
        Filter.Numeric(price, NumericOperator.Less, 5),
        Filter.Numeric(price, 5..10),
        Filter.Numeric(price, 10..25),
        Filter.Numeric(price, 25..100),
        Filter.Numeric(price, NumericOperator.Greater, 100)
    )
    val viewModel = FilterListViewModel.Numeric(filters)
    val connection = ConnectionHandler()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val view: FilterListView.Numeric = MyFilterListNumericAdapter() // your `FilterListView.Numeric` implementation
        connection += searcher.connectFilterState(filterState)
        connection += viewModel.connectFilterState(filterState)
        connection += viewModel.connectView(view)

        searcher.searchAsync()
    }

    override fun onDestroy() {
        super.onDestroy()
        connection.disconnect()
        searcher.cancel()
    }
}

Compose UI

InstantSearch provides the FilterListState as a state model, which is an implementation of the FilterListView interface. You need to connect FilterListState to the FilterListConnector or FilterListViewModel like any other FilterListView implementation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val filterState = FilterState()
    val price = Attribute("price")
    val groupColor = groupAnd(price)
    val numericFilters = listOf(
        Filter.Numeric(price, NumericOperator.Less, 5),
        Filter.Numeric(price, 5..10),
        Filter.Numeric(price, 10..25),
        Filter.Numeric(price, 25..100),
        Filter.Numeric(price, NumericOperator.Greater, 100)
    )
    val filterListState = FilterListState<Filter.Numeric>()
    val filterListConnector = FilterListConnector.Numeric(
        filters = numericFilters,
        filterState = filterState,
        groupID = groupColor
    )
    val connections = ConnectionHandler(filterListConnector)

    init {
        connections += searcher.connectFilterState(filterState)
        connections += filterListConnector.connectView(filterListState)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            filterListState.items.forEach { selectableFacet ->
                FilterRow( // your own UI composable to display `SelectableItem<Filter.Numeric>`
                    selectableFilter = selectableFacet,
                    onClick = { filterListState.onSelection?.invoke(it) }
                )
            }
        }
        searcher.searchAsync()
    }

    override fun onDestroy() {
        super.onDestroy()
        connections.disconnect()
        searcher.cancel()
    }
}

Parameters

Parameter Description
filters
type: List<Filter.Numeric>
Required

The numeric filters to display.

filterState
type: FilterState
Required

The FilterState that will hold your filters.

selectionMode
type: SelectionMode
default: Single
Optional

Whether the list can have Single or Multiple selections.

groupID
type: FilterGroupID
default: FilterGroupID(FilterOperator.And)
Optional

The identifier for the group of filters.

View

Parameter Description
view
type: FilterListView.Numeric
Optional

The view that renders the filters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
val view: FilterListView.Numeric = MyFilterListNumericAdapter()
filterListConnector.connectView(view)

// Example of `FilterListView.Numeric` implementation
class MyFilterListNumericAdapter : FilterListView.Numeric,
    ListAdapter<SelectableItem<Filter.Numeric>, FilterListViewHolder>(DiffUtilItem()) {
    override var onSelection: Callback<Filter.Numeric>? = null
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FilterListViewHolder {
        return FilterListViewHolder(parent.inflate(R.layout.list_item_selectable))
    }

    override fun onBindViewHolder(holder: FilterListViewHolder, position: Int) {
        val (filter, selected) = getItem(position)
        holder.bind(FilterPresenterImpl()(filter), selected) { onSelection?.invoke(filter) }
    }

    override fun setItems(items: List<SelectableItem<Filter.Numeric>>) {
        submitList(items)
    }
}

class DiffUtilItem<T : Filter> : DiffUtil.ItemCallback<SelectableItem<T>>() {
    override fun areItemsTheSame(oldItem: SelectableItem<T>, newItem: SelectableItem<T>): Boolean {
        return oldItem.first == newItem.first
    }

    override fun areContentsTheSame(oldItem: SelectableItem<T>, newItem: SelectableItem<T>): Boolean {
        return oldItem == newItem
    }
}
Did you find this page helpful?