Git Product home page Git Product logo

treeview's Introduction

TreeView

Maintainers Needed!See #12 for more details.

An TreeView implement in Android with RecyclerView written in kotlin.

CI Build Status maven-central GitHub license

Features

  1. 100% written in kotlin.
  2. Customise, in the future you can implement your own tree data structure.
  3. Fetching data asynchronously(Lazy load), no need to load all data at once.
  4. Horizontal scroll support. (with bug)
  5. Built-in DSL

Screenshot

output.webp output.webp

TODO

  • Select or Deselect Node
  • Better TreeNodeGenerator API
  • More API to operate the node in the tree, such as expand, collapse, etc.
  • Draggable nodes

Usage

  • Add the dependency to your gradle file
implementation("io.github.dingyi222666:treeview:1.3.1")
private fun createTree(): Tree<DataSource<String>> {
    val dataCreator: CreateDataScope<String> = { _, _ -> UUID.randomUUID().toString() }
    return buildTree(dataCreator) {
        Branch("app") {
            Branch("src") {
                Branch("main") {
                    Branch("java") {
                        Branch("com.dingyi.treeview") {
                            Leaf("MainActivity.kt")
                        }
                    }
                    Branch("res") {
                        Branch("drawable") {

                        }
                        Branch("xml") {}
                    }
                    Leaf("AndroidManifest.xml")
                }
            }
        }
    }
}
  • Create a node binder to bind the node to the layout, and in most case also implement node click events in this class

    Note: For the indentation setting of the item, we recommend using a Space widget placed at the visual leftmost of your item layout.

  • The width of this widget is the indentation width of the item.

inner class ViewBinder : TreeViewBinder<DataSource<String>>(),
    TreeNodeEventListener<DataSource<String>> {

    override fun createView(parent: ViewGroup, viewType: Int): View {
        return if (viewType == 1) {
            ItemDirBinding.inflate(layoutInflater, parent, false).root
        } else {
            ItemFileBinding.inflate(layoutInflater, parent, false).root
        }
    }

    override fun getItemViewType(node: TreeNode<DataSource<String>>): Int {
        if (node.isChild) {
            return 1
        }
        return 0
    }

    override fun bindView(
        holder: TreeView.ViewHolder,
        node: TreeNode<DataSource<String>>,
        listener: TreeNodeEventListener<DataSource<String>>
    ) {
        if (node.isChild) {
            applyDir(holder, node)
        } else {
            applyFile(holder, node)
        }

        val itemView = holder.itemView.findViewById<Space>(R.id.space)

        itemView.updateLayoutParams<ViewGroup.MarginLayoutParams> {
            width = node.depth * 22.dp
        }

    }

    private fun applyFile(holder: TreeView.ViewHolder, node: TreeNode<DataSource<String>>) {
        val binding = ItemFileBinding.bind(holder.itemView)
        binding.tvName.text = node.name.toString()
    }

    private fun applyDir(holder: TreeView.ViewHolder, node: TreeNode<DataSource<String>>) {
        val binding = ItemDirBinding.bind(holder.itemView)
        binding.tvName.text = node.name.toString()

        binding
            .ivArrow
            .animate()
            .rotation(if (node.expand) 90f else 0f)
            .setDuration(200)
            .start()
    }


    override fun onClick(node: TreeNode<DataSource<String>>, holder: TreeView.ViewHolder) {
        if (node.isChild) {
            applyDir(holder, node)
        } else {
            Toast.makeText(this@MainActivity, "Clicked ${node.name}", Toast.LENGTH_LONG).show()
        }
    }

    override fun onToggle(
        node: TreeNode<DataSource<String>>,
        isExpand: Boolean,
        holder: TreeView.ViewHolder
    ) {
        applyDir(holder, node)
    }
}
  • If you want to implement horizontal scrolling, you need to set the supportHorizontalScroll to true
treeview.supportHorizontalScroll = true
  • Now you can create the tree structure and set up the node generator and node binder for the TreeView, and then call refresh() to load the data
 val tree = createTree()

(binding.treeview as TreeView<DataSource<String>>).apply {
    bindCoroutineScope(lifecycleScope)
    this.tree = tree
    binder = ViewBinder()
    nodeEventListener = binder
}

lifecycleScope.launch {
    binding.treeview.refresh()
}
  • If you want to load dynamic data (etc. local file), you can see this example here

  • Done! Enjoy using it.

Special thanks

treeview's People

Contributors

code-factor avatar dingyi222666 avatar rosemoe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

treeview's Issues

java code

hi plz add java code to ReadMd tnks

Support Leaf of different type than Branch

Hi,

Thank you for creating this great library!

Is there a reason the data in a Leaf has to have the same type as the Branch?

fun <T : Any> DataSourceScope<T>.Leaf(
    name: String,
    data: T? = null
)

How to build a tree from dynamic data?

I have dynamic data, I want to build a tree from it.
Let me put an example.

I have my own Item

data class Item(
    val name: String,
    val childItems: List<Item>
)

I use dynamic Item.
For example:

val item = Item(
    "head", listOf(
        Item("1", listOf(
            Item("11", listOf()),
            Item("12", listOf())
        )),
        Item("2", listOf(
            Item("21", listOf()),
            Item("22", listOf())
        ))
    )
)

How can I create tree for this dynamic item?

private fun createTree(item: Item): Tree<DataSource<Item>> {
    val dataCreator: CreateDataScope<Item> = { name, item ->
        Item("", listOf())
    }

    return buildTree(dataCreator) {
        fun getSubBranches(item: =Item): List<Unit> {
            val branches: MutableList<Unit> = mutableListOf()

            item.childItems.forEach {
                branches.add(
                    Branch(it.name, item) {
                        getSubBranches(it)
                    }
                )
            }
            return branches
        }
        getSubBranches(item)
    }
}

I tried the above code, but I am getting 1 dimension tree and there are no subbranches.
How can I approach it?
Thank you!

Maintainers Needed

I have lost the motivation to keep continue this project, and I also have to maintain ChatLuna and other projects, so I don't have the energy to maintain this project.

Is anyone interested in this project and willing to continue maintaining it? You can reply under this issue, and I will give you read-write access to the repository.

刷新方式

当我使用
lifecycleScope.launch {
binding.treeView.refresh()
}
这个是怎么做到单个node刷新的,并且我如果两个node改变了,为什么不能一起刷新掉

动态添加很多数据,闪退

input parameter exceed reasonable range 1000000 4 2 0
2023-08-23 19:57:26.500 2077-2636/? E/DeviceMonitorPowerKit: not Satify ApplyResource
2023-08-23 19:57:26.542 13846-13920/com.iimt.robotarm E/AndroidRuntime: FATAL EXCEPTION: pool-6-thread-1
Process: com.iimt.robotarm, PID: 13846
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at java.util.AbstractList.hashCode(AbstractList.java:566)
at com.iimt.robotarm.result.TreeNodeData.hashCode(Unknown Source:81)
at io.github.dingyi222666.view.treeview.TreeNode.hashCode(treeNodes.kt:108)
at io.github.dingyi222666.view.treeview.TreeViewBinder.areContentsTheSame(TreeView.kt:667)
at io.github.dingyi222666.view.treeview.TreeViewBinder.areContentsTheSame(TreeView.kt:596)
at androidx.recyclerview.widget.AsyncListDiffer$1$1.areContentsTheSame(AsyncListDiffer.java:319)
at androidx.recyclerview.widget.DiffUtil$DiffResult.findMatchingItems(DiffUtil.java:702)
at androidx.recyclerview.widget.DiffUtil$DiffResult.(DiffUtil.java:675)
at androidx.recyclerview.widget.DiffUtil.calculateDiff(DiffUtil.java:178)
at androidx.recyclerview.widget.DiffUtil.calculateDiff(DiffUtil.java:106)
at androidx.recyclerview.widget.AsyncListDiffer$1.run(AsyncListDiffer.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:930)
2023-08-23 19:57:26.559 814-814/? E/SurfaceFlingerEx: Invalid parameter(s)!
2023-08-23 19:57:26.572 3184-4264/? E/HONOR_AWARENESS_AppGeneralCollectAbility: contained in blacklist : com.hihonor.android.launcher
2023-08-23 19:57:26.572 1025-2676/? E/ZrHung.AppEyeFocusWindow: NFW check!
2023-08-23 19:57:26.616 814-814/? E/SurfaceFlinger: checkContinuousFrameMiss ADD 1.
2023-08-23 19:57:26.616 814-814/? E/SurfaceFlingerEx: itouch VsyncOffsetInfo ERROR sfRefreshPoint is smaller than sfInvalidatPoint
2023-08-23 19:57:26.626 1983-2194/? E/BoosterUtil: convertSubIdToSlotId failed, subId:0, slotId:-1
2023-08-23 19:57:26.626 1983-2194/? E/BoosterUtil: getDefaultDataSlotId failed, invalid slotId:-1, subId:0
2023-08-23 19:57:26.626 1983-2194/? E/Booster_BroadcastProxy: [isDataOn]isDataOn failed, invalid slotId=-1
2023-08-23 19:57:26.628 814-916/? E/SurfaceFlingerEx: Invalid parameter(s)!
2023-08-23 19:57:26.635 814-814/? E/BpTransactionCompletedListener: Failed to transact (-32)
2023-08-23 19:57:26.635 814-814/? E/BpTransactionCompletedListener: Failed to transact (-32)
2023-08-23 19:57:26.651 814-1082/? E/SurfaceFlingerEx: Invalid parameter(s)!
2023-08-23 19:57:26.659 1983-9343/? E/HsmCoreServiceImpl: onTransact in code is: 102
2023-08-23 19:57:26.659 2035-2926/? E/AwareLog: Stub: processProcessDied has not been overridden!
2023-08-23 19:57:26.660 1983-2194/? E/DollieAdapterService: notifyActivityState pkg:com.iimt.robotarm/com.iimt.robotarm.app.MainVMActivity state:19 fg:false mUid:10267
2023-08-23 19:57:26.660 1983-2194/? E/BoosterUtil: convertSubIdToSlotId failed, subId:0, slotId:-1

How can I disable to collapse of root node?

Thanks for your great library.

I need your help.
I want to disable to collapse of the root node.
It means that the root node should be expanded forever.
Is there any way?

Thanks

点击事件

1、node.path这个目前是name拼接,如何把name换成depth输出呢
2、我需要点击子节点的箭头实现展示隐藏,而不是整个节点,该如何修改呢

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.