Flutter动画树视图插件animated_tree_view的使用

发布于 1周前 作者 yibo5220 来自 Flutter

Flutter动画树视图插件animated_tree_view的使用

animated_tree_view 是一个Flutter包,它提供了一种分层树状数据结构,可以将其可视化为线性列表视图。该组件基于Flutter熟悉的API AnimatedListSliverAnimatedList,并且支持移动、Web和桌面平台。

功能特性

  • 支持无限层级和子节点。
  • 节点展开和折叠时带有动画效果。
  • 可自定义缩进和范围线。
  • 提供添加、插入、移除以及展开/折叠节点的实用方法。
  • 可以轻松地横向或纵向遍历树。
  • 树差异工具(Tree Diff Util)用于计算两棵树之间的差异,并自动应用到树视图中。
  • 使用 ValueNotifier 和事件流监听变化。
  • 支持RTL布局。

如何使用

TreeView.simple 示例

TreeView.simple(
  tree: TreeNode.root(),
  builder: (context, node) {
    return ListTile(
      title: Text("Item ${node.level}-${node.key}"),
      subtitle: Text('Level ${node.level}'),
    );
  }
)

TreeView.indexed 示例

TreeView.indexed(
  tree: IndexedTreeNode.root(),
  builder: (context, node) {
    return ListTile(
      title: Text("Item ${node.level}-${node.key}"),
      subtitle: Text('Level ${node.level}'),
    );
  }
)

TreeView.simpleTyped 示例

TreeView.simpleTyped<CustomClass, TreeNode<CustomClass>>(
  tree: TreeNode<CustomClass>.root(),
  builder: (context, node) {
    return ListTile(
        title: Text("Item ${node.level}-${node.key}"),
        subtitle: Text('Level ${node.data?.foo}')
    );
  }     
)

SliverTreeView 示例

CustomScrollView(
  slivers: [
    SliverTreeView.simple(
      tree: TreeNode.root(),
      builder: (context, node) {
        return ListTile(
          title: Text("Item ${node.level}-${node.key}"),
          subtitle: Text('Level ${node.level}'),
        );
      },
    ),
  ],
);

配置与行为

属性名 描述
builder 构建函数,用于懒加载列表项。
tree 用于填充 TreeView 的树。如果树更新,则会使用 TreeDiffUtil 来获取新旧树之间的差异并应用更改。
scrollController 提供更细粒度控制滚动行为的控制器。
expansionIndicatorBuilder 基于节点数据构建动画扩展指示器。
indentation 绘制每个节点缩进样式的样式。
onItemTap 点击项目时触发的回调。
showRootNode 是否显示根节点。
expansionBehavior 控制节点展开时的行为。
onTreeReady TreeView 准备好时获取 TreeViewController 的回调。

完整示例代码

下面是一个完整的示例,展示了如何创建一个简单的动画树形视图:

import 'package:animated_tree_view/animated_tree_view.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Simple Animated Tree Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Simple Animated Tree Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({required this.title});

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TreeViewController? _controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () {
          if (sampleTree.isExpanded) {
            _controller?.collapseNode(sampleTree);
          } else {
            _controller?.expandAllChildren(sampleTree);
          }
        },
        label: ValueListenableBuilder<bool>(
          valueListenable: sampleTree.expansionNotifier,
          builder: (context, isExpanded, _) {
            return Text(isExpanded ? "Collapse all" : "Expand all");
          },
        ),
      ),
      body: TreeView.simple(
        tree: sampleTree,
        showRootNode: true,
        expansionIndicatorBuilder: (context, node) =>
            ChevronIndicator.rightDown(
              tree: node,
              color: Colors.blue[700],
              padding: const EdgeInsets.all(8),
            ),
        indentation: const Indentation(style: IndentStyle.roundJoint),
        onItemTap: (item) {
          print("Item tapped: ${item.key}");
        },
        onTreeReady: (controller) {
          _controller = controller;
          controller.expandAllChildren(sampleTree);
        },
        builder: (context, node) => Card(
          child: ListTile(
            title: Text("Item ${node.level}-${node.key}"),
            subtitle: Text('Level ${node.level}'),
          ),
        ),
      ),
    );
  }
}

final sampleTree = TreeNode.root()
  ..addAll([
    TreeNode(key: "0A")..add(TreeNode(key: "0A1A")),
    TreeNode(key: "0C")
      ..addAll([
        TreeNode(key: "0C1A"),
        TreeNode(key: "0C1B"),
        TreeNode(key: "0C1C")
          ..addAll([
            TreeNode(key: "0C1C2A")
              ..addAll([
                TreeNode(key: "0C1C2A3A"),
                TreeNode(key: "0C1C2A3B"),
                TreeNode(key: "0C1C2A3C"),
              ]),
          ]),
      ]),
    TreeNode(key: "0D"),
    TreeNode(key: "0E"),
  ]);

此代码片段演示了如何创建一个包含多个层级的树形结构,并通过 TreeView.simple 小部件将其渲染为可交互的UI元素。您可以根据需要调整配置选项以适应特定的应用场景。


更多关于Flutter动画树视图插件animated_tree_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter动画树视图插件animated_tree_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用animated_tree_view插件的代码示例。假设你已经通过pubspec.yaml文件添加了animated_tree_view依赖并运行了flutter pub get

pubspec.yaml

确保你的pubspec.yaml文件中包含以下依赖项:

dependencies:
  flutter:
    sdk: flutter
  animated_tree_view: ^x.y.z  # 请将x.y.z替换为最新版本号

main.dart

以下是一个完整的示例,展示如何使用animated_tree_view插件来创建一个动画树视图。

import 'package:flutter/material.dart';
import 'package:animated_tree_view/animated_tree_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Animated Tree View Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // 示例树数据
  final List<TreeViewNode> treeData = [
    TreeViewNode(
      title: 'Root',
      children: [
        TreeViewNode(
          title: 'Child 1',
          children: [
            TreeViewNode(title: 'Grandchild 1.1'),
            TreeViewNode(title: 'Grandchild 1.2'),
          ],
        ),
        TreeViewNode(
          title: 'Child 2',
          children: [
            TreeViewNode(title: 'Grandchild 2.1'),
          ],
        ),
      ],
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Animated Tree View Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: AnimatedTreeView(
          treeData: treeData,
          nodeBuilder: (context, node) {
            return ListTile(
              title: Text(node.title),
              trailing: Icon(
                node.expanded ? Icons.expand_more : Icons.chevron_right,
              ),
              onTap: () {
                setState(() {
                  node.expanded = !node.expanded;
                });
              },
            );
          },
        ),
      ),
    );
  }
}

// TreeViewNode 类定义(如果需要自定义,可以创建自己的类)
class TreeViewNode {
  String title;
  List<TreeViewNode> children;
  bool expanded = false;

  TreeViewNode({required this.title, this.children = const []});
}

注意事项

  1. TreeViewNode 类:在上面的代码中,我们定义了一个简单的TreeViewNode类来表示树节点。如果你需要更复杂的数据结构,可以自定义这个类。

  2. AnimatedTreeView 组件AnimatedTreeView组件接受treeData(树节点数据列表)和nodeBuilder(用于构建每个节点的Widget)。nodeBuilder函数接收上下文和当前节点作为参数,并返回一个Widget。

  3. 展开/折叠逻辑:在onTap回调中,我们简单地切换节点的expanded状态。这将触发动画并显示或隐藏子节点。

这个示例应该能够帮助你快速上手animated_tree_view插件。你可以根据需要进一步自定义节点样式、动画效果等。

回到顶部