mirror of
https://github.com/AdrianKuta/Expandable-RecyclerView.git
synced 2025-04-19 23:19:02 +02:00
Improved function for finding not collapsed nodes.
This commit is contained in:
parent
263cff975c
commit
4380ddf9a8
@ -15,7 +15,7 @@ android {
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "0.0.1-alpha02"
|
||||
versionName "0.0.1-beta01"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
|
@ -6,33 +6,77 @@ import com.github.adriankuta.datastructure.tree.TreeNode
|
||||
class ExpandableTreeNode<T>(value: T) : TreeNode<T>(value) {
|
||||
|
||||
var expanded: Boolean = true
|
||||
set(value) {
|
||||
field = value
|
||||
children.forEach {
|
||||
(it as ExpandableTreeNode).expanded = value
|
||||
}
|
||||
}
|
||||
|
||||
override fun child(value: T, childDeclaration: ChildDeclaration<T>?) {
|
||||
val newChild = ExpandableTreeNode(value)
|
||||
override fun child(child: T, childDeclaration: ChildDeclaration<T>?) {
|
||||
val newChild = ExpandableTreeNode(child)
|
||||
if (childDeclaration != null)
|
||||
newChild.childDeclaration()
|
||||
addChild(newChild)
|
||||
}
|
||||
|
||||
fun getVisibleNodeCount(): Int {
|
||||
return onlyVisibleItems()
|
||||
/**
|
||||
* @param skipRootNode If `True`, then root node won't be counted.
|
||||
*/
|
||||
internal fun getVisibleNodeCount(skipRootNode: Boolean): Int {
|
||||
var size = onlyVisibleItems()
|
||||
.size
|
||||
|
||||
if (skipRootNode && size > 0)
|
||||
size--
|
||||
|
||||
return size
|
||||
}
|
||||
|
||||
fun getVisibleNode(position: Int): ExpandableTreeNode<T> {
|
||||
return onlyVisibleItems()[position]
|
||||
/**
|
||||
* This function use Pre-order iteration to go through tree:
|
||||
* ```
|
||||
* e.g.
|
||||
* 1
|
||||
* / | \
|
||||
* / | \
|
||||
* 2 3 4
|
||||
* / \ / | \
|
||||
* 5 6 7 8 9
|
||||
* / / | \
|
||||
* 10 11 12 13
|
||||
*
|
||||
* Output (skipRootNode = false): 1 2 5 10 6 11 12 13 3 4 7 8 9
|
||||
* Output (skipRootNode = true): 2 5 10 6 11 12 13 3 4 7 8 9
|
||||
* ```
|
||||
* @param skipRootNode If `True` root element will be omitted, and position 0 will be for first left child.
|
||||
*/
|
||||
internal fun getVisibleNode(position: Int, skipRootNode: Boolean): ExpandableTreeNode<T> {
|
||||
val nodePosition = if (skipRootNode) position + 1 else position
|
||||
return onlyVisibleItems()[nodePosition]
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of nodes which parent or higher ancestor aren't collapsed.
|
||||
*/
|
||||
private fun onlyVisibleItems(): List<ExpandableTreeNode<T>> {
|
||||
//Visible if parent of node is expanded.
|
||||
return map { it as ExpandableTreeNode }
|
||||
.filter { (it.parent as? ExpandableTreeNode)?.expanded ?: true }
|
||||
.filter { allAncestorsAreExpanded(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* `Ancestor` is a node reachable by repeated proceeding from child to parent.
|
||||
* @return `True` if parent, and all parent's ancestors are expanded.
|
||||
*/
|
||||
private fun allAncestorsAreExpanded(node: ExpandableTreeNode<T>): Boolean {
|
||||
var ancestor = parent as? ExpandableTreeNode
|
||||
var ancestorsAreExpanded = isAncestorExpanded(ancestor)
|
||||
|
||||
while (ancestorsAreExpanded && ancestor != null) {
|
||||
ancestor = ancestor.parent as? ExpandableTreeNode<T>
|
||||
ancestorsAreExpanded = ancestorsAreExpanded.and(isAncestorExpanded(ancestor))
|
||||
}
|
||||
|
||||
return ancestorsAreExpanded
|
||||
}
|
||||
|
||||
private fun isAncestorExpanded(ancestor: ExpandableTreeNode<T>?): Boolean {
|
||||
return ancestor?.expanded ?: true
|
||||
}
|
||||
|
||||
}
|
@ -12,25 +12,35 @@ abstract class MultilevelRecyclerViewAdapter<T, VH : RecyclerView.ViewHolder> :
|
||||
abstract override fun onCreateViewHolder(parent: ViewGroup, nestLevel: Int): VH
|
||||
|
||||
final override fun onBindViewHolder(holder: VH, position: Int) {
|
||||
onBindViewHolder(holder, treeNodes.getVisibleNode(position))
|
||||
val visibleNode = treeNodes.getVisibleNode(position, true)
|
||||
onBindViewHolder(holder, visibleNode, visibleNode.depth())
|
||||
}
|
||||
|
||||
abstract fun onBindViewHolder(holder: VH, treeNode: ExpandableTreeNode<T>)
|
||||
abstract fun onBindViewHolder(holder: VH, treeNode: ExpandableTreeNode<T>, nestLevel: Int)
|
||||
|
||||
abstract fun getTreeNodes(): ExpandableTreeNode<T>
|
||||
|
||||
final override fun getItemCount(): Int {
|
||||
treeNodes = getTreeNodes()
|
||||
return treeNodes.getVisibleNodeCount()
|
||||
return treeNodes.getVisibleNodeCount(true) //We don't want to show root element.
|
||||
}
|
||||
|
||||
final override fun getItemViewType(position: Int): Int {
|
||||
|
||||
return treeNodes.getVisibleNode(position).depth()
|
||||
return treeNodes.getVisibleNode(position, true).depth()
|
||||
}
|
||||
|
||||
fun toggleGroup(expandableTreeNode: ExpandableTreeNode<T>) {
|
||||
expandableTreeNode.expanded = !expandableTreeNode.expanded
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun expand(expandableTreeNode: ExpandableTreeNode<T>) {
|
||||
expandableTreeNode.expanded = true
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun collapse(expandableTreeNode: ExpandableTreeNode<T>) {
|
||||
expandableTreeNode.expanded = false
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user