HierarchicalConnector(
searcher: HitsSearcher,
attribute: Attribute,
filterState: FilterState,
hierarchicalAttributes: List<Attribute>,
separator: String
)
A Hierarchical Menu
is a component that displays a hierarchical navigation menu, based on facet attributes.
Examples
class MyActivity : AppCompatActivity() {
val searcher = HitsSearcher(
applicationID = ApplicationID("YourApplicationID"),
apiKey = APIKey("YourSearchOnlyAPIKey"),
indexName = IndexName("YourIndexName")
)
val hierarchicalCategory = Attribute("categories")
val hierarchicalCategoryLvl0 = Attribute("$categories.lvl0")
val hierarchicalCategoryLvl1 = Attribute("$categories.lvl1")
val hierarchicalCategoryLvl2 = Attribute("$categories.lvl2")
val hierarchicalAttributes = listOf(
hierarchicalCategoryLvl0,
hierarchicalCategoryLvl1,
hierarchicalCategoryLvl2
)
val filterState = FilterState()
val separator = " > "
val hierarchical = HierarchicalConnector(
searcher = searcher,
attribute = hierarchicalCategory,
filterState = filterState,
hierarchicalAttributes = hierarchicalAttributes,
separator = separator
)
val connection = ConnectionHandler(hierarchical, searcher.connectFilterState(filterState))
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view : HierarchicalView = HierarchicalAdapter() // your HierarchicalView implementation
connection += hierarchical.connectView(view, HierarchicalPresenterImpl(separator))
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
connection.disconnect()
searcher.cancel()
}
}
Low-level API
If you want to fully control the Hierarchical Menu components and connect them manually,
use the following components:
Searcher
. The Searcher
that handles your searches.
FilterState
. The current state of the filters.
HierarchicalViewModel
. The logic applied to the hierarchical facets.
HierarchicalView
. The concrete hierarchical view.
HierarchicalPresenter
. The presenter that controls the sorting and other settings of the hierarchical menu.
HierarchicalItem
. A single node in the hierarchy.
class MyActivity : AppCompatActivity() {
val searcher = HitsSearcher(
applicationID = ApplicationID("YourApplicationID"),
apiKey = APIKey("YourSearchOnlyAPIKey"),
indexName = IndexName("YourIndexName")
)
val filterState = FilterState()
val hierarchicalCategory = Attribute("categories")
val hierarchicalCategoryLvl0 = Attribute("$categories.lvl0")
val hierarchicalCategoryLvl1 = Attribute("$categories.lvl1")
val hierarchicalCategoryLvl2 = Attribute("$categories.lvl2")
val hierarchicalAttributes = listOf(
hierarchicalCategoryLvl0,
hierarchicalCategoryLvl1,
hierarchicalCategoryLvl2
)
val separator = " > "
val viewModel = HierarchicalViewModel(hierarchicalCategory, hierarchicalAttributes, separator)
val connection = ConnectionHandler()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view: HierarchicalView = HierarchicalAdapter() // your `HierarchicalView` implementation
connection += searcher.connectFilterState(filterState)
connection += viewModel.connectFilterState(filterState)
connection += viewModel.connectSearcher(searcher)
connection += viewModel.connectView(view, HierarchicalPresenterImpl(separator))
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
searcher.cancel()
connection.disconnect()
}
}
Compose UI
InstantSearch provides HierarchicalState
as a state model,
which implements the HierarchicalView
interface.
You need to connect HierarchicalState
to the HierarchicalConnector
or HierarchicalViewModel
like any other HierarchicalView
implementation.
class MyActivity : AppCompatActivity() {
val searcher = HitsSearcher(
applicationID = ApplicationID("YourApplicationID"),
apiKey = APIKey("YourSearchOnlyAPIKey"),
indexName = IndexName("YourIndexName")
)
val hierarchicalCategory = Attribute("categories")
val hierarchicalCategoryLvl0 = Attribute("$categories.lvl0")
val hierarchicalCategoryLvl1 = Attribute("$categories.lvl1")
val hierarchicalCategoryLvl2 = Attribute("$categories.lvl2")
val hierarchicalAttributes = listOf(
hierarchicalCategoryLvl0,
hierarchicalCategoryLvl1,
hierarchicalCategoryLvl2
)
val filterState = FilterState()
val separator = " > "
val hierarchicalState = HierarchicalState()
val hierarchical = HierarchicalConnector(
searcher = searcher,
attribute = hierarchicalCategory,
filterState = filterState,
hierarchicalAttributes = hierarchicalAttributes,
separator = separator
)
val connections = ConnectionHandler(hierarchical)
init {
connections += searcher.connectFilterState(filterState)
connections += hierarchical.connectView(hierarchicalState, HierarchicalPresenterImpl(separator))
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
LazyColumn {
items(hierarchicalState.hierarchicalItems) { item ->
HierarchicalItem( // your own UI composable to display `HierarchicalItem`
item = item,
onClick = { hierarchicalState.onSelectionChanged?.invoke(item.facet.value) }
)
}
}
}
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
connections.disconnect()
searcher.cancel()
}
}
Parameters
The Searcher
that handles your searches.
The names of the hierarchical attributes that you need to target, in ascending order.
The delimiter used to separate hierarchical facets.
Usually something like ” > ”, including spaces as shown in this example.
View
The view that renders the hierarchical menu.
presenter
HierarchicalPresenter
required
How to display the list of HierarchicalItem
.
Takes a list of HierarchicalItem
and returns a new list of HierarchicalItem
.
A HierarchicalItem
contains a Facet
, its level
, and a displayName
.val view: HierarchicalView = HierarchicalAdapter()
val separator = " > "
val presenter = HierarchicalPresenterImpl(separator)
hierarchical.connectView(view, presenter)
// Example of `HierarchicalView` implementation
class HierarchicalAdapter : HierarchicalView,
ListAdapter<HierarchicalItem, HierarchicalViewHolder>(DiffUtilItem()) {
override var onSelectionChanged: Callback<String>? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HierarchicalViewHolder {
return HierarchicalViewHolder(parent.inflate(R.layout.list_item_selectable, false))
}
override fun onBindViewHolder(holder: HierarchicalViewHolder, position: Int) {
val item = getItem(position)
holder.bind(item) { onSelectionChanged?.invoke(item.facet.value) }
}
override fun setTree(tree: List<HierarchicalItem>) {
submitList(tree)
}
}
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
}
}