B4A Library [Class] Treeview Class (Tree and Node)

After finding how to communicate between classes I improved the previous version and since it is completely different, I opened a new thread for it.

There is a Tree class, in which you have to define the nature of the tree (what database it displays). This class manages the nodes which are defined by another class.

I implemented a horizontal "scroll panel" to compensate for the scrollview's lack of it.

The main is a demo with one tree in portrait and two trees in landscape node.

Edit: Version 3 has automatic setting of the treeview panel height and width, so linewidth is calculated, not supplied.
The datalist is sorted.
Arrows added to the slidepanel to hint about its use.
Edit: version 3 updated to have automatic width reduction when nodes close.
Version 4 can scroll horizontally thanks to Informatix additions.
Edit: version 5 use Informatix new 2D ScrollView.

Edit: Updated to ver. 6 :
- The tree is isolated from the specific use (like file manager or family tree), the definition of the data that populates the nodes is done at the calling activity using sub GetData which is called by the tree when required.( Edit: not all the way, in the node_open you still have to change the tag and the text of the new nodes to suit other kinds of trees...)
- LongClick on a node is passed for action to the calling activity to a sub NodeLongClicked.
- OpenRoot method enables display of the root node open (by code, the user can of course open it by pressing the + button)
- NullImages - Possibility to remove the images of file and folder (the label will move left accordingly).
- Wait cursor activated smartly (!!) only when opening nodes with many children, not to slow the program too much.

Edit: Updated to ver. 7 :
See details in this post. http://www.b4x.com/forum/additional...ss-treeview-class-tree-node-3.html#post149450

Edit: updated to ver. 8, the only change from 7 is that data type is in the tree class , not in the main.
Also the Reflection library is not used and can be ticked off.

Edit: update to ver 9. I saw that with new devices of high resolution the lineheight is too large so I adjusted it to give better results for all devices.
If you encounter line size problems please tell me (with the specific device parameter).

Edit: see post #85 for a method to open all nodes of the tree by code.

Looking forward to get feedback !

Note: For B4A ver. 7 replace in tree line 190 Doevent with sleep(0)
 

Attachments

  • screen3.png
    screen3.png
    58.8 KB · Views: 3,016
  • screen4.png
    screen4.png
    57.7 KB · Views: 2,634
  • Treeview9.1.zip
    24.6 KB · Views: 1,000
Last edited:

JOTHA

Well-Known Member
Licensed User
Longtime User
Hi derez,

thank you again for helping me.
This was exactly what I did yesterday (I made a copy out of the IDE menu/help system):
B4X:
Dim cd As ColorDrawable
    Dim NodeLabelColor As Int
    NodeLabelColor = Colors.RGB(255, 165, 0)  '-- orange --
    cd.Initialize(NodeLabelColor, 10dip)
    TN.lbl.Background = cd
... and it works well ... but after that all nodes are in color orange.

Let me tell you, what I want to have as solution:
In the tree there are folders which have no subfolders (= 0 nodes), some have 1 subfolder (= 1 node) and some have 2 subfolders (= 2 nodes).

The result of the code should be, that the folders have different colors:
0 nodes = LabelColor = Orange / TextColor = Black
1 node = LabelColor = LightBlue / TextColor = Black
2 nodes = LabelColor = Blue / TextColor = White

Because it was difficult to find out how much folders have subfolders (and so on ...), I have written the CountNumber into the text as "[0]" ... "[1]" ... "[2]"
Then I coded in module tree (in Sub Initialize(Module ...)
B4X:
.
.
.

    Dim LblColor0, LblColor1, LblColor2 As Int
    LblColor0 = Colors.RGB(255, 165, 0)  '-- orange = FFA500 --
    LblColor1 = Colors.RGB(100, 149, 237)  '-- Hellblau = 6495ED --
    LblColor2 = Colors.RGB(0, 0, 155)  '-- Dunkelblau = #00009B --
  
'    Dim TN As NodeC
'    TN.Initialize
  
    TextColor(0) = Colors.Black
    LblColor(0) = LblColor0
    cd.Initialize(LblColor0, 10dip)
'    TN.lbl.Background = cd

    TextColor(1) = Colors.Black
    LblColor(1) = LblColor1
    cd.Initialize(LblColor1, 10dip)
'    TN.lbl.Background = cd

    TextColor(2) = Colors.White
    LblColor(2) = LblColor2
    cd.Initialize(LblColor2, 10dip)
'    TN.lbl.Background = cd

.
.
.

Then I coded in module main ...
B4X:
If st.Contains("[1]") Then
         da.ColorSet = 1
       Else If st.Contains("[2]") Then
         da.ColorSet = 2
       Else
         da.ColorSet = 0
       End If
This worked fine with the code before, but now this code doesn't work. All nodes are in Color Orange.

The "old" code works very well and the priority is not to have rounded corners in the Label (it just would be "nice to have").

I think, it isn't worth to spend a lot of time in this little case. ;-)

So, thanks again for your support!
 
Last edited:

derez

Expert
Licensed User
Longtime User
This is because you defined this color in the node class so every node gets this color.
The color should be sent to the node while initializing it through the labelcolor parameter:
B4X:
Sub Initialize(Module As Tree, _
               parent As Node, _
               level As Int, _
               linewidth As Int, _
               lineheight As Int, _
               Text As String, _
               TextSize As Int, _
               TextColor As Int, _
               LabelColor As Int, _
               img As Bitmap, _
               tag As String, _
               tag1 As String     )
...

Now this color should be defined in the Tree class where you initialize new nodes - in sub node_open.
In that sub you know how many children nodes belong to the opened node (and it does a for-next loop too init all the nodes), so there you can assign different color to the children nodes according to their quantity.

If you don't need the round corner - use the label.color instead of background. If you want it as an option it should be added to the initialization sub, either as boolean or as corner-radius size parameter.
 

derez

Expert
Licensed User
Longtime User
Hello derez,

one more question:
How can I create this "old-style-design" for a tree like you can see in the attached picture?
I mean the lines on the levels ...

View attachment 52701
I know, it must be done with images, bitmaps ... but how can I put them into the different places on the levels?

Thank you again in advance!

The way I found is a partial solution - to draw lines on all the tree area, just as helper to see the tree levels. The lines are not connected to any node. Let me know if anyone is interested.
This solution is implemented in B4J, I don't think that on a small screen it is needed.
 

Attachments

  • lines.png
    lines.png
    32.4 KB · Views: 435
Last edited:
Top