unit_tree_flutter

Customize your tree UI with no limit! By mainly focusing on data structure, you can customize the tree UI with various styles.

Table of contents

Demonstration

By default, you can apply 8 basic variants from this package: Stack/Expanded widgets X Multiple-choice/Single-choice X Eager-loading/Lazy-loading.

1. Stack widgets

  • 1.1. MStackWidget: Multiple choice, eager loading.
  • 1.2. MLazyStackWidget: Multiple choice, lazy loading.
  • 1.3. SStackWidget: Single choice, eager loading.
  • 1.4. SLazyStackWidget: Single choice, lazy loading.

2. Expanded widgets

  • 2.1. MExpandedWidget: Multiple choice, eager loading.
  • 2.2. MLazyExpandedWidget: Multiple choice, lazy loading.
  • 2.3. SExpandedWidget: Single choice, eager loading.
  • 2.4. SLazyExpandedWidget: Single choice, lazy loading.

Quick Start

1. Introduce tree data structure

Tree data structure & algorithms is taken from this package: unit_tree_data_structure.

The property isUnavailable is defined by default as: If a branch doesn't contains any leaf, it is unavailable (or un-chosenable).

2. With eager loading style

Use TreeType.fromJson() to parse data from Map to TreeType. REMEMBER to call updateAllUnavailableNodes(tree) before return:

TreeType<EasyNodeType> sampleData() {
  Map<String, dynamic> data = {
    "data": {
      "id": 0,
      "title": "Root: Level 0",
    },
    "children": [
      {
        "data": {
          "id": 11,
          "title": "(Inner) Ex title: Level 1.1",
        },
        "children": [
          {
            "data": {
              "id": 21,
              "title": "(Inner) Ex title: Level 2.1",
            },
            "children": [
              {
                "data": {
                  "id": 31,
                  "title": "(Leaf) Ex title: Level 3.1",
                  "isInner": false,
                },
              },
              {
                "data": {
                  "id": 32,
                  "title": "(Leaf) Ex title: Level 3.2",
                  "isInner": false,
                },
              },
              {
                "data": {
                  "id": 33,
                  "title": "(Leaf) Ex title: Level 3.3",
                  "isInner": false,
                },
              },
            ],
          },
          {
            "data": {
              "id": 22,
              "title": "(Inner) Ex title: Level 2.2",
            },
            "children": [
              {
                "data": {
                  "id": 34,
                  "title": "(Leaf) Ex title: Level 3.4",
                  "isInner": false,
                },
              },
            ],
          },
          {
            "data": {
              "id": 23,
              "title": "(Inner) Ex title: Level 2.3",
            },
          },
        ],
      },
      {
        "data": {
          "id": 12,
          "title": "(Inner) Ex title: Level 1.2",
        },
      },
    ],
  };

  var tree = TreeType.fromJson<EasyNodeType>(
    json: data,
    parent: null,
    implFromJson: EasyNodeType.fromJson,
  );

  // it is VERY important to call this function
  updateAllUnavailableNodes(tree);

  return tree;
}

Then, simply put that data into your widgets:

initData = sampleData();

return MExpandedWidget(initData); // or
return SExpandedWidget(initData)`. // or
return MStackWidget([initData]); // or
return SStackWidget([initData]);

3. With lazy loading style

Lazy loading widgets receive a Future function to get the children nodes every click:

Future<List<TreeType<T>>> Function(TreeType<T> parent) fGetChildrenFunc;

You can read the example source code here: MLazyExpandedScreen.

root = createRoot();

Future<List<TreeType<EasyNodeType>>> fGetChildrenFunc(
    TreeType<EasyNodeType> parent) async {
  List<TreeType<EasyNodeType>> newChildren;
  setState(() => isLoading = true);
  
  newChildren = implementationXYZ(parent);

  await Future.delayed(const Duration(seconds: 1));
  setState(() => isLoading = false);
  return newChildren;
}

return MLazyExpandedWidget(
  root,
  fGetChildrenFunc: fGetChildrenFunc,
); // or

return SLazyExpandedWidget(
  root,
  fGetChildrenFunc: fGetChildrenFunc,
); // or

return MLazyStackWidget
  [root],
  fGetChildrenFunc: fGetChildrenFunc,
); // or

return SLazyStackWidget(
  [root],
  fGetChildrenFunc: fGetChildrenFunc,
);

Ask: I want to customize the UI?

You can use the UIProperties to customize several parts of UI.

Ask: I want to customize the UI even MOREEEE!!

Like I said from the beginning, the strength of this package is it mainly focuses on tree data structure & algorithms. Therefore, as long as you keep the current logic & use functions correctly, you can make any UI that you want!

Just Copy-Paste the widget most similar to your desired UI. Don't hesitate to do it! Source code is very short & easy to read. If you face any problem, you can create an issue in GitHub.

Libraries

unit_tree_flutter