mirror of
https://github.com/AdrianKuta/Expandable-RecyclerView.git
synced 2025-04-20 07:29: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
|
minSdkVersion 23
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "0.0.1-alpha02"
|
versionName "0.0.1-beta01"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
consumerProguardFiles 'consumer-rules.pro'
|
consumerProguardFiles 'consumer-rules.pro'
|
||||||
|
@ -6,33 +6,77 @@ import com.github.adriankuta.datastructure.tree.TreeNode
|
|||||||
class ExpandableTreeNode<T>(value: T) : TreeNode<T>(value) {
|
class ExpandableTreeNode<T>(value: T) : TreeNode<T>(value) {
|
||||||
|
|
||||||
var expanded: Boolean = true
|
var expanded: Boolean = true
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
children.forEach {
|
|
||||||
(it as ExpandableTreeNode).expanded = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun child(value: T, childDeclaration: ChildDeclaration<T>?) {
|
override fun child(child: T, childDeclaration: ChildDeclaration<T>?) {
|
||||||
val newChild = ExpandableTreeNode(value)
|
val newChild = ExpandableTreeNode(child)
|
||||||
if (childDeclaration != null)
|
if (childDeclaration != null)
|
||||||
newChild.childDeclaration()
|
newChild.childDeclaration()
|
||||||
addChild(newChild)
|
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
|
.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>> {
|
private fun onlyVisibleItems(): List<ExpandableTreeNode<T>> {
|
||||||
//Visible if parent of node is expanded.
|
//Visible if parent of node is expanded.
|
||||||
return map { it as ExpandableTreeNode }
|
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
|
abstract override fun onCreateViewHolder(parent: ViewGroup, nestLevel: Int): VH
|
||||||
|
|
||||||
final override fun onBindViewHolder(holder: VH, position: Int) {
|
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>
|
abstract fun getTreeNodes(): ExpandableTreeNode<T>
|
||||||
|
|
||||||
final override fun getItemCount(): Int {
|
final override fun getItemCount(): Int {
|
||||||
treeNodes = getTreeNodes()
|
treeNodes = getTreeNodes()
|
||||||
return treeNodes.getVisibleNodeCount()
|
return treeNodes.getVisibleNodeCount(true) //We don't want to show root element.
|
||||||
}
|
}
|
||||||
|
|
||||||
final override fun getItemViewType(position: Int): Int {
|
final override fun getItemViewType(position: Int): Int {
|
||||||
|
return treeNodes.getVisibleNode(position, true).depth()
|
||||||
return treeNodes.getVisibleNode(position).depth()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleGroup(expandableTreeNode: ExpandableTreeNode<T>) {
|
fun toggleGroup(expandableTreeNode: ExpandableTreeNode<T>) {
|
||||||
expandableTreeNode.expanded = !expandableTreeNode.expanded
|
expandableTreeNode.expanded = !expandableTreeNode.expanded
|
||||||
notifyDataSetChanged()
|
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