mirror of
				https://github.com/AdrianKuta/Expandable-RecyclerView.git
				synced 2025-10-31 00:43:39 +01:00 
			
		
		
		
	Improved function for finding not collapsed nodes.
This commit is contained in:
		| @@ -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() | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user