Git Product home page Git Product logo

flutter_tree_view's People

Contributors

bambinoua avatar baumths avatar mz2 avatar naory159 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  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

flutter_tree_view's Issues

How can I add nodes and rebuild

I try to use your tree using blocs. Is it possible, to rebuild nodes after new children have been added to nodes?

Here is a part of my test code:

    return BlocProvider(
      create: (context) => DirectoryTreeBloc()
        ..add(
          DirectoriesRequestedEvent(),
        ),
      child: BlocBuilder<DirectoryTreeBloc, DirectoryTreeState>(
        builder: (context, state) {
          final rootNode = state.rootNode;

          final treeController = TreeController<TreeNodeData>(
            roots: [rootNode],
            childrenProvider: (node) {
              return node.children ?? const [];
            },
          );

          return Material(
            child: Column(
              children: [
                Expanded(
                  child: AnimatedTreeView(
                    treeController: treeController,
                    nodeBuilder: (context, entry) {
                      return TreeIndentation(
                        entry: entry,
                        child: Row(
                          children: [
                            FolderButton(
                              splashRadius: 20,
                              isOpen: treeController.getExpansionState(
                                entry.node,
                              ),
                              onPressed: () => treeController.toggleExpansion(
                                entry.node,
                              ),
                            ),
                            Text(entry.node.title),
                          ],
                        ),
                      );
                    },
                  ),
                ),

After new nodes are found in the repository a new state is emitted which results in rebuild. The new node appears after I toggle state of the parent or click a sibling node. But what must I change for get the new node appearing after rebuild?

I hope it can be done as I do not want to use any other tree..

Autoscroll to node?

I've implemented your treeview in my project and it works fine so, by first, many thanks for your job.
In some case, I have very extended trees, so I would like to implement a function to search a node, using for example the "find" method and than autoscroll to tree view to that node. Is there some method that can I use fo this?

how add childs for node dynamic?

I have the same problam, I want click Folder icon, get data from server api, add childs for node dynamic, and auto expand the node.
onAboutToExpand dose not seem to support async.

image

#11

Is there an physics in TreeView?

Have a nice day, your library is very good and I am using it in my project.
But I have a problem, shouldAutoScroll: true when I select the last node in the list, the treeView will be pushed up unnecessarily. Is there any way to fix it?

Would be better if TreeNode<T>

Very nice lib!
It would be better if treeNode has generic type to make it easier to access data's fields without cast.

`TreeView` and `AnimatedTreeView` does not refresh on `treeController` change

Below the simple code which I use:

BlocBuilder(
  builder: (context, state) {
    controller ??= FancyTreeController(); // controller can be re-created

    return AnimatedTreeView(
      treeController: controller,
      ...
    );
  },
)

If controller is re-created with new nodes (for example search result) the AnimatedTreeView is not refreshed. The similar issue in for TreeView.

Add a depth limit

A depthLimit to be mentioned which controls the expanding depth of nodes. if node depth is greater than mentioned limit then the children should expand with same indentation as parent avoiding further indentation

Scrollbar does not work

First, thank you for the tree view widget. I threw trees with millions of nodes at the widget and it still handles them well. But scrollbar does not work.

Step to show the problem:

  1. load the demo example: https://mbaumgartenbr.github.io/flutter_tree_view/#/
  2. minimize windows so that if you scroll with mouse, scrollbar shows up
  3. if you drag the scrollbar, the pane on the right get scrolled instead of the tree pane (which is on the left).

This happens on web, macos and windows; haven't tried on other platforms.

Needs simple concrete example

I like the package, but finding the example overly complex to work through and it would benefit from a simpler concrete example that shows how the basic of the package would work... so far, its a bit custom to implement what should be a simple tree view.

How to use provider (riverpod) in the childrenProvider

I have a riverpod StateNotifierProvider reading files from a directory asynchronously. I would like to use it in my tree controller to to provide the child nodes which will be fetched onPressed. I am unable to read a provider in the childrenProvider as it throws a StackOverflow error.

The AnimatedTreeView is contained in a HookConsumerWidget. Reason behind using hooks is to maintain a state of the widget tree's expansion.

final treeController = useState(TreeController<FileSystemEntity>(
    roots: roots,
    childrenProvider: (FileSystemEntity parent) => ref.read(projectFilesProvider.notifier).getProjectRootFiles() ?? const Iterable.empty(),
  ));

Stack Trace:

The following StackOverflowError was thrown building SizeTransition(animation: AnimationController#2f3bb(▶ 1.000)➩CurveTween(curve: _Linear)➩1.0, state: _AnimatedState#c9986):
Stack Overflow

When the exception was thrown, this was the stack: 
#0      ProviderContainer.readProviderElement.<anonymous closure>.<anonymous closure> (package:riverpod/src/framework/container.dart:445:40)
#1      _HashMapKeyIterable.forEach.<anonymous closure> (dart:collection-patch/collection_patch.dart:491:13)
#2      _HashMap.forEach (dart:collection-patch/collection_patch.dart:153:15)
#3      ProviderElementBase.visitAncestors (package:riverpod/src/framework/element.dart:849:24)
#4      ProviderContainer.readProviderElement.<anonymous closure> (package:riverpod/src/framework/container.dart:445:25)
#5      ProviderContainer.readProviderElement (package:riverpod/src/framework/container.dart:477:8)
#6      ProviderElementProxy.read (package:riverpod/src/framework/proxy_provider_listenable.dart:114:26)
#7      useTreeControllerForFileSystemEntities.<anonymous closure> (package:quinine/hooks/tree.dart:29:56)
#8      TreeController.depthFirstTraversal.createTreeEntriesRecursively (package:flutter_fancy_tree_view/src/tree_controller.dart:386:54)
...
#1893   TreeController.depthFirstTraversal.createTreeEntriesRecursively (package:flutter_fancy_tree_view/src/tree_controller.dart:399:11)
#1894   TreeController.depthFirstTraversal (package:flutter_fancy_tree_view/src/tree_controller.dart:411:7)
#1895   _SliverAnimatedTreeState._buildSubtree (package:flutter_fancy_tree_view/src/sliver_animated_tree.dart:197:23)
#1896   _SubtreeState.initState (package:flutter_fancy_tree_view/src/sliver_animated_tree.dart:411:45)
#1897   StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5101:55)
#1898   ComponentElement.mount (package:flutter/src/widgets/framework.dart:4944:5)
...     Normal element mounting (7 frames)
#1905   Element.inflateWidget (package:flutter/src/widgets/framework.dart:3953:16)
#1906   Element.updateChild (package:flutter/src/widgets/framework.dart:3676:20)
#1907   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4993:16)
#1908   StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5133:11)
#1909   Element.rebuild (package:flutter/src/widgets/framework.dart:4690:5)
#1910   BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2743:19)
#1911   WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:863:21)
#1912   RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:381:5)
#1913   SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1289:15)
#1914   SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1218:9)
#1915   SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1076:5)
#1916   _invoke (dart:ui/hooks.dart:145:13)
#1917   PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:338:5)
#1918   _drawFrame (dart:ui/hooks.dart:112:31)

right-to-left treeview

hi, thanks for share your code, this help me a lot.
just I have question: I want to set right-to-left tree, but I cannot found how to change line in tree.
How can I do this?

How to show sorted treeview?

Do you have any recommendations on how best to add node sorting when displaying the tree view ?

Or is this something you can add so that each node, and children are sorted depending on some node-based sort method ??

how can flutter_tree_view and getx be used together?

mycode like is:

1.AController.dart

  Map<String, List<String>> treeData = {
    '': [''],
  }.obs;

  void updateTreeData(Map<String, List<String>> data) {
    treeData = data;
  }

2.treeview

**AController myController = Get.put(AController());**

void generateSampleTree(TreeNode parent) {
  **final childrenIds = myController.treeData[parent.id];**
  if (childrenIds == null) return;
  parent.addChildren(
    childrenIds.map(
      (String childId) => TreeNode(id: childId, label: childId),
    ),
  );
  parent.children.forEach(generateSampleTree);
}

late final TreeViewController treeController;
const String kRootId = '#root#';
final rootNode = TreeNode(id: kRootId, label: kRootId);
generateSampleTree(rootNode);

treeController = TreeViewController(
  rootNode: rootNode,
);

final root = treeController.find('/');
if(root != null){
  log('get...' + root.id);
  treeController.expandNode(root);
}

final treeViewTheme = ValueNotifier(const TreeViewTheme());
late final scrollController = ScrollController();

ValueListenableBuilder<TreeViewTheme>(
          valueListenable: treeViewTheme,
          builder: (_, treeViewTheme, __) {
            return Scrollbar(
              thumbVisibility: false,
              controller: scrollController,
              child: TreeView(
                controller: treeController,
                theme: treeViewTheme,
                scrollController: scrollController,
                nodeHeight: nodeHeight.value,
                nodeBuilder: (BuildContext context, TreeNode node) {
                  return InkWell(
                    onTap: () {
                         //------------
                    },
                    onLongPress: () {
                      // appController.toggleSelection(nodeScope.node.id)
                    },
                    child: ValueListenableBuilder<ExpansionButtonType>(
                      valueListenable: expansionButtonType,
                      builder: (context, ExpansionButtonType buttonType, __) {
                        return Row(
                            children: [
                              const LinesWidget(),
                              NodeWidgetLeadingIcon(
                                useFoldersOnly: true,
                              ),
                              const SizedBox(width: 1),
                              Text(node.label, overflow: TextOverflow.ellipsis),
                            ]
                        );
                      },
                    ),
                  );
                },
              ),
            );
          },
        ),
  1. update treedata
    final root = {
      '#root#': ['/']
    };
root['/'] = ['aaa', 'bbb'];

myController.updateTreeData(root);

but it can not update.

`TreeController.collapseCascading()` has a funky behavior when paired with `SliverAnimatedTree`

Problem:

When calling TreeController.collapseCascading() the algorithm traverses the tree setting the expansion state of all nodes in the subtrees of the provided nodes to false and then calls TreeController.rebuild() which causes SliverAnimatedTree to rebuild its internal flat tree.

When SliverAnimatedTree rebuilds its flat tree, it collects the nodes that need to be animated comparing its previous and current expansion states and calls setState().

The internal _TreeEntry widget then creates and animates the _Subtree which builds its own flat subtree to display all animating nodes in a Column in the same tile under the subtree's root node widget.

When building this subtree, the nodes already got the new expansion state of false leading to their subtrees not being traversed and only the first level of descendants of the subtree being collected by the flattening algorithm.

The user sees all nodes further down the subtree disappearing immediately and the very first level of the subtree animating out, which is undesirable.

Possible solution:

Update the collapseCascading() method to only collapse the nodes on the iterable that was passed to it before calling rebuild() then traverse the tree collapsing all nodes of the subtrees after rebuild() is called.

This could have unwanted side effects for listeners that rely on the state being already updated when they are called

This behavior could be hidden behind an optional boolean parameter on the collapseCascading() method allowing the users to choose to prioritize animations over state integrity. This new parameter would likely be called rebuildEarly with false as the default, choosing to preserve state integrity over animations.

Is it possible to have no interaction ?

Hello

Is it possible to display a full expanded tree view, but to not have any interaction with it ?
Just display hierarchical data, just scrollable, but with no click on the nodes.

Each row of the current node must not occupy the maximum space

Hello!Thank you.Thank you for yourThanks for the package!

But I found a problem when I used it and couldn't solve it.

I used the following code to realize that a checkbox checkbox is displayed on the rightmost side of the phone, but the position is never close to the rightmost side, always leaving a blank distance.
After checking your code, I still don't know what is causing this.

Can you help me?

TreeIndentation(
            entry: entry,
            // Provide an indent guide if desired. Indent guides can be used to
            // add decorations to the indentation of tree nodes.
            // This could also be provided through a DefaultTreeIndentGuide
            // inherited widget placed above the tree view.
            guide: const IndentGuide.connectingLines(indent: 48),
            // The widget to render next to the indentation. TreeIndentation
            // respects the text direction of `Directionality.maybeOf(context)`
            // and defaults to left-to-right.
            child: Padding(
              padding: const EdgeInsets.fromLTRB(4, 8, 8, 8),
              child: Row(
                children: [
                  // Add a widget to indicate the expansion state of this node.
                  // See also: ExpandIcon.
                  // FolderButton(
                  //   isOpen: entry.hasChildren ? entry.isExpanded : null,
                  //   onPressed: entry.hasChildren ? onTap : null,
                  // ),
                  if (entry.hasChildren)
                    ExpandIcon(
                      key: GlobalObjectKey(entry.node),
                      isExpanded: entry.isExpanded,
                      onPressed: (_) =>
                          treeController.toggleExpansion(entry.node),
                    ),
                  Flexible(
                    child: Text(entry.node.title),
                  ),
                  Expanded(child: SizedBox()),
                  if (entry.node.children.isEmpty)
                    Checkbox(
                      checkColor: Colors.white,
                      // fillColor: MaterialStateProperty.resolveWith(getColor),
                      value: false,
                      onChanged: (bool? value) {
                        widget.onSelected(entry.node);
                      },
                    ),
                ],
              ),
            ),
          )

d1748051824f8584d8f7bb620a0c859

Best Way to Scroll Horizontally and Vertically

I am trying to use InteractiveViewer to try to scroll a large tree. The horizontal scrolling works normal, however my vertical scrolling snaps back to my original view as soon as I stop the scroll. I am new to flutter_tree_view as well as InteractiveViewer, and moderately familiar with flutter. Is this a bug, or am I setting something wrong? This snippet uses your MinimalTreeView unaltered. Thank you!

InteractiveViewer(
constrained: false,
child: Container(
height: 1000,
width: 1000,
child:
MinimalTreeView(),
)),

Is there any better way to filter nodes?

kRootId: ['A', 'B', 'C', 'D', 'E', 'F'],
  'A': ['A 1', 'A 2'],
  'A 2': ['A 2 1'],
  'B': ['B 1', 'B 2', 'B 3'],
  'B 1': ['B 1 1'],
  'B 1 1': ['B 1 1 1', 'B 1 1 2'],
  'B 2': ['B 2 1'],
  'B 2 1': ['B 2 1 1'],
  'C': ['C 1', 'C 2', 'C 3', 'C 4'],
  'C 1': ['C 1 1'],
  'D': ['D 1'],
  'D 1': ['D 1 1'],
  'E': ['E 1'],
  'F': ['F 1', 'F 2'],

For example, when I search B 2 1 1 the tree remains nodes B,B 2,B 2 1 and B 2 1 1, while search content is empty it shows original tree data.

How to have tree fully expanded at start and on refresh?

I have a Flutter app where I am using the 'flutter_tree_view' widget.

A couple of questions:

  1. What is the best way of making sure the tree is fully expanded on initial display? I was expecting there to be an 'fully expanded at start' property that coul; be set at the tree level.
  2. In my app I can add new nodes to the tree, but I can't find a way of refreshing the tree so that it is also fully expanded after it is refreshed. Any suggestions?

An error is reported when the outer layer is wrapped with a horizontal rolling component

Failed assertion: line 1979 pos 12: 'hasSize'

PostControllerScope( controller: appController, child: FutureBuilder<void>( future: appController.hello(), builder: (_, __) { if (appController.isInitialized) { return ValueListenableBuilder<TreeViewTheme>( valueListenable: appController.treeViewTheme, builder: (_, treeViewTheme, __) { return Scrollbar( isAlwaysShown: true, controller: appController.scrollController, child: SingleChildScrollView( child: TreeView( controller: appController.treeController, theme: treeViewTheme, scrollController: appController.scrollController, nodeHeight: appController.nodeHeight, nodeBuilder: (_, __) => GestureDetector( child: ValueListenableBuilder<ExpansionButtonType>( valueListenable: appController.expansionButtonType, builder: (context, ExpansionButtonType buttonType, __) { return Row( children: const [ LinesWidget(), NodeWidgetLeadingIcon(useFoldersOnly: true), IconChip(), SizedBox(width: 8), Expanded(child: NodeTitle()), ] ); }, ), ), ), ), ); }, ); } return const Center(child: CircularProgressIndicator()); }, ), )

Adding a vertical scroll bar to the tree

@baumths, Thanks for the earlier help with horizontal and vertical scroll. I apologize that I do not know git well enough yet to message you direct with this question (I assume it is possible). Could you please advise how I could add a vertical scroll bar to a tree? It looks like there are several inherited properties used in your package that might do this... but I am sorry I do not know how to set them. 1M thanks.

How to show selected node ?

How do I show the UI that the node I'm selecting? I see there is onTab function but it doesn't have this function.

Strange behavior when updating tree using asynchronous data

In some situations, we need to fetch tree children from server before expand.

late final _dynamicController = TreeViewController(
    onAboutToExpand: (TreeNode nodeAboutToExpand) async {
      if (treeController != _dynamicController) return;

      // add this line
      await Future.delayed(const Duration(milliseconds: 300));

      final children = _dynamicChildrenMap[nodeAboutToExpand.id];

      if (children != null) {
        nodeAboutToExpand.addChildren(
          children.map((child) => TreeNode(id: child, label: child)),
        );
      }
    },
    rootNode: TreeNode(id: 'Root')
      //? Initial Dynamic Nodes
      ..addChild(TreeNode(id: 'A', label: 'A'))
      ..addChild(TreeNode(id: 'B', label: 'B'))
      ..addChild(TreeNode(id: 'C', label: 'C')),
  );

Then it behave like this, I need to retap the expander to let the tree update.

SM-G9550_20210603173513.mp4

Am I using it wrong way? How should I update the treeView after load data async.

Change TreeView when use StreamBuilder

Hi, thank you for awesome package!
In my project, I use StreamBuilder to change data (create, delete, edit) but TreeView not displayed according to new data. What I have to do?
Thank.

Selected node not highlighted

Hello,
Thanks for this great package, I updated from version 0.5 and I noticed that the selected node is no more highlighted, and the associated property is missing.
Thank you.

how to add OnTap on each Node?

Hello first of all a great package so far. It looks very good.
I have one quick question. I want to add a onTap or onPressed Method to a Node. Not on the sign thats expend or collapse it. How can i achieve this. I'am still new to dart/flutter so be please with me :).
I can see that the node object in the simple view is still a simple object not an widget.

Thx for replying, Eric

Change all Icons to Widget

To support other (non Material) icons, can you change the type to Widget for all the custom icon types?

Expand All or scroll to node?

Is it possible to expand all nodes, or scroll to one?

It looks like #7 has been implemented, but can't figure out how it works.

How to dynamically load tree for selected root?

I have an initial tree which contains few roots

root 1
root 2
root 3         > // this one has children

I want to load the tree which belongs to root 3 when user clicks on FolderButton. Certainly I want to do loading when node is in collapsed state but all tree nodes are expanded by default. (I think that is a bug moreover if node is a leaf so how can it be expanded or collapsed?)

To change expansion state I need to call controller.toggleExpansion(node) each time user clicks on FolderButton. But when I call it on expanded node it will be collapsed so I need to do click again? And finally I need to load tree after expanding! So how to implement tree loading on demand? How can I subscribe on expansion state change?

Re-ordering and Moving Nodes

I'm implementing a drag and drop, and the treeController won't update properly when moving around nodes, is there a way to reboot the treeController to just rebuild everything? All the data looks right in the treeMap, but when the treeController builds, it just doesn't seem the adjust nodes for some reason.

This happens a lot when having nodes expanded and then dragging that parent around and asking the treeController to update.

Library building

Hello Matheus Baumgarten ,

I need to make complex views, How could I make a similar complex library like yours from scratch?
What do I need to learn to master complex views?

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.