[译]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 文档


相关推荐
「、皓子~1 天前
海狸IM 2.1 正式发布
flutter·微服务·golang·electron·开源软件·im·海狸im
里欧跑得慢1 天前
AI 驱动的 UI 国际化方案自动适配:从单一语言到多语言布局的智能转换
前端·css·flutter·web
恋猫de小郭1 天前
AI 时代,一个优化 Flutter 的重复代码工具 Deslop
android·前端·flutter
ljt27249606612 天前
Flutter笔记--envied
前端·笔记·flutter
加农炮手Jinx2 天前
Flutter for OpenHarmony 实战:flutter_animate 声明式动画让 UI 灵动如原生
flutter·ui·华为·harmonyos·鸿蒙
里欧跑得慢2 天前
Flutter 像素级还原:设计稿到代码的视觉无损转换技巧
前端·css·flutter·web
里欧跑得慢2 天前
Flutter 三方库 function_tree — 鸿蒙应用开发中的动态数学公式解析与计算神器,实现鸿蒙深度适配下的复杂函数逻辑运行时求值实战(适配鸿蒙 HarmonyOS Next ohos)
android·前端·安全·flutter·华为·harmonyos
吃西瓜的年年3 天前
vue3原理思维导图
vue.js·笔记·flutter
GitLqr4 天前
从代码复用走向生态:Flutter Dart Package 实战全指南
flutter·全栈·dart