[译]Flutter 强大灵活的树形组件 flutter_fancy_tree_view

Flutter 强大灵活的树形组件 flutter_fancy_tree_view

原文链接:flutter_fancy_tree_view | Flutter Package (flutter-io.cn)

译时版本:1.4.1


flutter_fancy_tree_view

Flutter 组件和 sliver(滑动内容)的集合,可用于将层级数据可视化。

该库使用了回调集以深度优先顺序来遍历层级数据,将所需信息收集到 Dart 的List(树的扁平展示)中, 然后使用 sliver 在屏幕上渲染树的节点。

截图

空白缩进
连接线
范围标线

安装

运行以下命令:

csharp 复制代码
flutter pub add flutter_fancy_tree_view

它会向包的 pubspec.yaml 中添加如下的代码行(会自动运行 flutter pub get):

yaml 复制代码
dependencies:
  flutter_fancy_tree_view: any

现在在 Dart 代码中,可如下使用:

arduino 复制代码
import 'package:flutter_fancy_tree_view/flutter_fancy_tree_view.dart';

⚠️ 警告

请将版本 '1.0' 作为一个全新的包来看待。不鼓励从旧版本升级,因为该包大部分已经重写,并有很多破坏性改动。

特性

  • 动态 "树节点" 模型
  • 可使用任何组件
  • 缩进向导
  • 展开/折叠动画
  • sliver 树变体
  • 支持基本的拖拽

要体验这些特性,可访问 live 示例应用。 示例应用的源代码可在 example目录中找到。

开始

前往 example/example.md查看一下该包基本用法的示例,示例的注释很完善。 也可以在 example/lib/src/examples 查看一些特定特性的示例。

用法

  1. 创建一个 "树节点" 模型来存储数据
kotlin 复制代码
class MyTreeNode {
  const MyTreeNode({
    required this.title,
    this.children = const <MyTreeNode>[],
  });

  final String title;
  final List<MyTreeNode> children;
}
  1. 创建/获取层级数据
csharp 复制代码
final List<MyTreeNode> roots = [
  const MyTreeNode(title: 'My static root node'),
  ...fetchOtherRootNodes(),
];
  1. 初始化树控制器 TreeController
ini 复制代码
final treeController = TreeController<MyTreeNode>(
  roots: roots,
  childrenProvider: (MyTreeNode node) => node.children,
);

注意: 如查打算使用拖拽特性,确保在 TreeController 中包含 parentProvider 。一些方法如 expandAncestorscheckNodeHasAncestor 依赖 parentProvider 运转。不设置时会在调试模式抛出断言错误。

  1. 将控制器传给树视图 TreeView ,然后提供一个组件构建器将数据映射为组件。确保包含树节点展开状态的方式和缩进组件TreeIndentation以适当地缩进它们。
less 复制代码
@override
Widget build(BuildContext context) {
  return AnimatedTreeView<MyTreeNode>(
    treeController: treeController,
    nodeBuilder: (BuildContext context, TreeEntry<MyTreeNode> entry) {
      return InkWell(
        onTap: () => treeController.toggleExpansion(entry.node),
        child: TreeIndentation(
          entry: entry,
          child: Text(entry.node.title),
        ),
      );
    },
  );
}

拖拽

对于可用示例,可前往 example/lib/src/examples 目录下的拖拽示例代码。

该包提供了两个新的组件 TreeDraggableTreeDragTarget ,它们封装了 Flutter 的 DraggableDragTarget 组件,添加了一些树视图需要的处理,如悬停时自动展开/折叠的节点、在可滚动的视口组件垂直边缘附近拖拽时自动滚动,等。

现在修改一下前面的例子来包含拖拽特性。

首先,修改"树节点"模型来包含父节点的引用,这是一个重要的步骤,它能确保展开/折叠行为能正常动作。

kotlin 复制代码
class MyTreeNode {
  MyTreeNode({
    required this.title,
    Iterable<MyTreeNode>? children,
  }) : children = <MyTreeNode>[] {
    if (children == null) return;

    for (final MyTreeNode child in children) {
      this.children.add(child);

      // 确保更新目标节点的子组件时能更新它的父节点。
      child.parent = this;
    }
  }

  final String title;
  final List<MyTreeNode> children;
  MyTreeNode? parent;
}

修改了树节点模型后,现在确保 TreeController 包含 parentProvider 回调以访问目标树节点的祖先。 对于拖拽特性非常重要,对于方法如 expandAncestors 也很重要。如果 parentProvider 没有定义,则会使用总是返回 null (例,(MyTreeNode node) => null)的回调,并且需要它的方法会在调试模式下会抛出断言错误。

ini 复制代码
final treeController = TreeController<MyTreeNode>(
  ...,
  parentProvider: (MyTreeNode node) => node.parent,
);

现在,修改树节点组件以包含 TreeDraggableTreeDragTarget 组件。

less 复制代码
@override
Widget build(BuildContext context) {
  return AnimatedTreeView<MyTreeNode>(
    treeController: treeController,
    nodeBuilder: (BuildContext context, TreeEntry<MyTreeNode> entry) {
      return TreeDragTarget<MyTreeNode>(
        node: entry.node,
        onNodeAccepted: (TreeDragAndDropDetails details) {
          // 可选,确保目标节点已展开,所以在树重新构建时被拖拽的节点在其附近是可见的。
          treeController.setExpansionState(details.targetNode, true);

          // TODO: 实现树的重排序逻辑

          // 确保重新构建树视图以在新的附近表示重排序后的节点。
          treeController.rebuild();
        },
        builder: (BuildContext context, TreeDragAndDropDetails? details) {
          Widget myTreeNodeTile = Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(entry.node.title),
          );

          // 如果 details 不为空,拖拽的节点会悬停在拖拽目标上。可添加一些反馈给用户。
          if (details != null) {
            myTreeNodeTile = ColoredBox(
              color: Theme.of(context).colorScheme.primary.withOpacity(0.3),
              child: myTreeNodeTile,
            );
          }

          return TreeDraggable<MyTreeNode>(
            node: entry.node,

            // 在拖拽的指针下面向用户表示一些反馈,这可以是任意组件。
            feedback: IntrinsicWidth(
              child: Material(
                elevation: 4,
                child: myTreeNodeTile,
              ),
            ),

            child: InkWell(
              onTap: () => treeController.toggleExpansion(entry.node),
              child: TreeIndentation(
                entry: entry,
                child: myTreeNodeTile,
              ),
            ),
          );
        },
      );
    },
  );
}

API 文档

前往 pub.dev api 文档


相关推荐
忆江南11 小时前
iOS 深度解析
flutter·ios
明君8799711 小时前
Flutter 实现 AI 聊天页面 —— 记一次 Markdown 数学公式显示的踩坑之旅
前端·flutter
恋猫de小郭12 小时前
移动端开发稳了?AI 目前还无法取代客户端开发,小红书的论文告诉你数据
前端·flutter·ai编程
MakeZero15 小时前
Flutter那些事-交互式组件
flutter
shankss15 小时前
pull_to_refresh_simple
flutter
shankss15 小时前
Flutter 下拉刷新库新特性:智能预加载 (enableSmartPreload) 详解
flutter
SoaringHeart2 天前
Flutter调试组件:打印任意组件尺寸位置信息 NRenderBox
前端·flutter
九狼2 天前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
_squirrel3 天前
记录一次 Flutter 升级遇到的问题
flutter
Haha_bj3 天前
Flutter——状态管理 Provider 详解
flutter·app