FilterRangeConnector(
filterState: FilterState,
attribute: Attribute,
bounds: ClosedRange<T>?,
range: ClosedRange<T>?
)
Filter Numeric Range is a filtering view made to filter between two numeric values.
The most common interface for this is a slider.
The Android View and Compose UI code samples (part of the Android widget showcase repository on GitHub) illustrate the use of sliders.
Examples
class MyActivity : AppCompatActivity() {
val searcher = HitsSearcher(
applicationID = ApplicationID("YourApplicationID"),
apiKey = APIKey("YourSearchOnlyAPIKey"),
indexName = IndexName("YourIndexName")
)
val price = Attribute("price")
val groupID = FilterGroupID(price)
val primaryBounds = 0..15
val initialRange = 0..15
val filters = filters {
group(groupID) {
range(price, initialRange)
}
}
val filterState = FilterState(filters)
val range = FilterRangeConnector(
filterState = filterState,
attribute = price,
range = initialRange,
bounds = primaryBounds
)
val connection = ConnectionHandler(range, searcher.connectFilterState(filterState))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view: NumberRangeView<Int> = MyNumberRangeView(textLabel) // your `NumberRangeView<T>` implementation
connection += range.connectView(view)
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
connection.disconnect()
searcher.cancel()
}
}
Low-level API
If you want to fully control the Filter Numeric Range components and connect them manually, use the following components:
Searcher. The Searcher that handles your searches.
FilterState. The current state of the filters.
FilterRangeViewModel. The logic applied to the numeric ranges.
NumberRangeView. The view that renders the numeric range filter.
class MyActivity : AppCompatActivity() {
val searcher = HitsSearcher(
applicationID = ApplicationID("YourApplicationID"),
apiKey = APIKey("YourSearchOnlyAPIKey"),
indexName = IndexName("YourIndexName")
)
val filterState = FilterState()
val attribute = Attribute("price")
val viewModel = FilterRangeViewModel<Int>()
val connection = ConnectionHandler()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view: NumberRangeView<Int> = MyNumberRangeView(textLabel) // your `NumberRangeView<T>` implementation
connection += searcher.connectFilterState(filterState)
connection += viewModel.connectFilterState(filterState, attribute)
connection += viewModel.connectView(view)
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
connection.disconnect()
searcher.cancel()
}
}
Compose UI
InstantSearch provides the NumberRangeState as a state model,
which is an implementation of the NumberRangeView interface.
You need to connect NumberRangeState to the FilterRangeConnector or FilterRangeViewModel like any other NumberRangeView implementation.
class MyActivity : AppCompatActivity() {
val searcher = HitsSearcher(
applicationID = ApplicationID("YourApplicationID"),
apiKey = APIKey("YourSearchOnlyAPIKey"),
indexName = IndexName("YourIndexName")
)
val price = Attribute("price")
val groupID = FilterGroupID(price)
val primaryBounds = 0..15
val initialRange = 0..15
val filters = filters {
group(groupID) {
range(price, initialRange)
}
}
val filterState = FilterState(filters)
val sliderState = NumberRangeState<Int>()
val range = FilterRangeConnector(
filterState = filterState,
attribute = price,
range = initialRange,
bounds = primaryBounds
)
val connections = ConnectionHandler(range)
init {
connections += searcher.connectFilterState(filterState)
connections += range.connectView(sliderState)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyRangeSlider(sliderState) // your own UI composable to display range and bounds as `Range<T>`
}
searcher.searchAsync()
}
fun Range<Int>.toClosedFloatRange(): ClosedFloatingPointRange<Float> {
return min.toFloat()..max.toFloat()
}
override fun onDestroy() {
super.onDestroy()
connections.disconnect()
searcher.cancel()
}
}
Parameters
The limits of the acceptable range within which values are coerced.
The range of values within the bounds.
View
The view that renders the numeric range filter.val view = MyNumberRangeView(textLabel)
range.connectView(view)
// Example of `NumberRangeView<T>` implementation
class MyNumberRangeView(val view: TextView) : NumberRangeView<Int> {
override var onRangeChanged: Callback<Range<Int>>? = null
private var bounds: Range<Int>? = null
override fun setBounds(bounds: Range<Int>?) {
this.bounds = bounds
view.text = bounds?.let {
"Bounds: ${it.min} to ${it.max}"
} ?: "No bounds"
}
override fun setRange(range: Range<Int>?) = Unit
}