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
}
}