diff --git a/README.md b/README.md
index 2668283..eda96fa 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# Gapo Tree View
-Support TreeView for RecyclerView with highly customizable
+Support TreeView for RecyclerView with highly customizable and search support
## Demo
diff --git a/app/src/main/java/com/gapo/treeview/MultiChoiceActivity.kt b/app/src/main/java/com/gapo/treeview/MultiChoiceActivity.kt
index da19f91..0412442 100644
--- a/app/src/main/java/com/gapo/treeview/MultiChoiceActivity.kt
+++ b/app/src/main/java/com/gapo/treeview/MultiChoiceActivity.kt
@@ -1,13 +1,16 @@
package com.gapo.treeview
+import android.annotation.SuppressLint
import android.content.res.ColorStateList
import android.graphics.Color
-import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
+import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatCheckBox
+import androidx.appcompat.widget.AppCompatEditText
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
+import androidx.core.widget.addTextChangedListener
import com.gg.gapo.treeviewlib.GapoTreeView
import com.gg.gapo.treeviewlib.model.NodeState
import com.gg.gapo.treeviewlib.model.NodeViewData
@@ -16,6 +19,7 @@ class MultiChoiceActivity : AppCompatActivity(), GapoTreeView.Listener
+ @SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_multi_choice)
@@ -26,6 +30,21 @@ class MultiChoiceActivity : AppCompatActivity(), GapoTreeView.Listener(R.id.searchEditText)?.addTextChangedListener {
+ treeView.filter { nodeViewData ->
+ val searchText = it?.toString()?.lowercase() ?: ""
+
+ if (searchText.isBlank())
+ return@filter true
+
+ // if any children match the search, show parents too
+ val hierarchyList = nodeViewData.getData().getHierarchyNodeChild()
+ hierarchyList.any {
+ searchText in it.name.lowercase()
+ }
+ }
+ }
}
override fun onBind(
diff --git a/app/src/main/java/com/gapo/treeview/SampleModel.kt b/app/src/main/java/com/gapo/treeview/SampleModel.kt
index 98f144d..d92d5cc 100644
--- a/app/src/main/java/com/gapo/treeview/SampleModel.kt
+++ b/app/src/main/java/com/gapo/treeview/SampleModel.kt
@@ -2,7 +2,6 @@ package com.gapo.treeview
import android.os.Bundle
import com.gg.gapo.treeviewlib.model.NodeData
-import com.gg.gapo.treeviewlib.model.NodeViewData
data class SampleModel(
override val nodeViewId: String,
diff --git a/app/src/main/java/com/gapo/treeview/SingleChoiceActivity.kt b/app/src/main/java/com/gapo/treeview/SingleChoiceActivity.kt
index 5a4dc0f..8a0dbb0 100644
--- a/app/src/main/java/com/gapo/treeview/SingleChoiceActivity.kt
+++ b/app/src/main/java/com/gapo/treeview/SingleChoiceActivity.kt
@@ -1,12 +1,13 @@
package com.gapo.treeview
-import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.AppCompatEditText
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatRadioButton
import androidx.appcompat.widget.AppCompatTextView
-import androidx.recyclerview.widget.RecyclerView
+import androidx.core.widget.addTextChangedListener
import com.gg.gapo.treeviewlib.GapoTreeView
import com.gg.gapo.treeviewlib.model.NodeViewData
@@ -24,6 +25,21 @@ class SingleChoiceActivity : AppCompatActivity(), GapoTreeView.Listener(R.id.searchEditText)?.addTextChangedListener {
+ treeView.filter { nodeViewData ->
+ val searchText = it?.toString()?.lowercase() ?: ""
+
+ if (searchText.isBlank())
+ return@filter true
+
+ // if any children match the search, show parents too
+ val hierarchyList = nodeViewData.getData().getHierarchyNodeChild()
+ hierarchyList.any {
+ searchText in it.name.lowercase()
+ }
+ }
+ }
}
override fun onBind(
diff --git a/app/src/main/res/layout/activity_multi_choice.xml b/app/src/main/res/layout/activity_multi_choice.xml
index 5384ea3..e65ab36 100644
--- a/app/src/main/res/layout/activity_multi_choice.xml
+++ b/app/src/main/res/layout/activity_multi_choice.xml
@@ -1,5 +1,19 @@
-
\ No newline at end of file
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_single_choice.xml b/app/src/main/res/layout/activity_single_choice.xml
index 5384ea3..e65ab36 100644
--- a/app/src/main/res/layout/activity_single_choice.xml
+++ b/app/src/main/res/layout/activity_single_choice.xml
@@ -1,5 +1,19 @@
-
\ No newline at end of file
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5fbe90a..b95ad46 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,4 @@
GapoTreeView
+ Search
\ No newline at end of file
diff --git a/treeview/src/main/java/com/gg/gapo/treeviewlib/GapoTreeView.kt b/treeview/src/main/java/com/gg/gapo/treeviewlib/GapoTreeView.kt
index 3714a39..1f11f77 100644
--- a/treeview/src/main/java/com/gg/gapo/treeviewlib/GapoTreeView.kt
+++ b/treeview/src/main/java/com/gg/gapo/treeviewlib/GapoTreeView.kt
@@ -29,6 +29,7 @@ class GapoTreeView private constructor(
adapters: Pair>>
) {
+ private var filterPredicate: (NodeViewData) -> Boolean = { true }
private val nodes = mutableListOf>()
private val nodesShowOnUI = mutableListOf>()
private var treeViewAdapter: TreeViewAdapter? = null
@@ -191,11 +192,13 @@ class GapoTreeView private constructor(
if (isLastNode) {
nodesShowOnUI.addAll(
nodes.filter { it.parentNodeIds.contains(nodeId) && it.nodeLevel == parentNode.nodeLevel + 1 }
+ .filter(filterPredicate)
)
} else {
nodesShowOnUI.addAll(
min(nodesShowOnUI.size - 1, parentNodeIndex + 1),
nodes.filter { it.parentNodeIds.contains(nodeId) && it.nodeLevel == parentNode.nodeLevel + 1 }
+ .filter(filterPredicate)
)
}
requestUpdateTree()
@@ -297,6 +300,41 @@ class GapoTreeView private constructor(
}
}
+ @Suppress("UNCHECKED_CAST")
+ fun filter(predicate: (NodeViewData) -> Boolean) {
+ this.filterPredicate = predicate
+
+ val filterNodes = nodes.filter(predicate)
+
+ nodesShowOnUI.clear()
+ nodesShowOnUI.addAll(filterNodes)
+
+ // expand all parent nodes
+ filterNodes.forEach { nodeViewData ->
+ val parentNodeIds = nodeViewData.parentNodeIds
+ parentNodeIds.forEach { parentNodeId ->
+ nodesShowOnUI.find { it.nodeId == parentNodeId }?.isExpanded = true
+ }
+
+ val data = nodeViewData.getData() as NodeData
+ val hierarchyList = data.getHierarchyNodeChild() as List>
+ if (hierarchyList.size <= 1) {
+ nodeViewData.isExpanded = false
+ return@forEach
+ }
+
+ val isContainChildren =
+ hierarchyList.subList(1, hierarchyList.size).any { hierarchyNodeData ->
+ nodesShowOnUI.any { it.nodeId == hierarchyNodeData.nodeViewId }
+ }
+
+ nodeViewData.isExpanded = isContainChildren
+ nodeViewData.isLeaf = !isContainChildren
+ }
+
+ requestUpdateTree()
+ }
+
private fun findNodeLevel(node: NodeViewData): Int {
return node.parentNodeIds.size
}
diff --git a/treeview/src/main/java/com/gg/gapo/treeviewlib/model/NodeData.kt b/treeview/src/main/java/com/gg/gapo/treeviewlib/model/NodeData.kt
index 903e02a..489c4ca 100644
--- a/treeview/src/main/java/com/gg/gapo/treeviewlib/model/NodeData.kt
+++ b/treeview/src/main/java/com/gg/gapo/treeviewlib/model/NodeData.kt
@@ -16,4 +16,11 @@ interface NodeData {
fun areContentsTheSame(item: NodeData): Boolean
fun getChangePayload(item: NodeData): Bundle
+
+ @Suppress("UNCHECKED_CAST")
+ fun getHierarchyNodeChild(): List {
+ return mutableListOf(this as T).apply {
+ getNodeChild().forEach { this += it.getHierarchyNodeChild() }
+ }
+ }
}
\ No newline at end of file