You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中实现Workflow Builder UI:容器连线方案咨询

Flutter 实现工作流容器连线的方案

一、自定义绘制(最灵活)

核心用CustomPainter实现容器间的连线,步骤如下:

  • 记录容器位置:给每个工作流容器绑定GlobalKey,通过key.currentContext?.findRenderObject()获取容器的全局坐标与尺寸,计算出连线的起点(比如容器右侧中点)和终点(下一个容器左侧中点)。
  • 绘制连线:自定义CustomPainter类,在paint方法里用Canvas.drawLine绘制基础连线,若需要箭头,用Path绘制三角形箭头形状。
  • 叠加绘制层:用Stack布局,把容器放在下层,自定义绘制层放在上层,确保连线不会被容器遮挡。

示例代码片段:

// 获取容器右侧中点的全局坐标
Offset getContainerRightMid(GlobalKey key) {
  final renderBox = key.currentContext?.findRenderObject() as RenderBox?;
  if (renderBox == null) return Offset.zero;
  final pos = renderBox.localToGlobal(Offset.zero);
  final size = renderBox.size;
  return Offset(pos.dx + size.width, pos.dy + size.height / 2);
}

// 自定义连线绘制器
class ConnectionPainter extends CustomPainter {
  final List<Offset> linePoints;
  final Color lineColor;
  final double lineWidth;

  ConnectionPainter({
    required this.linePoints,
    this.lineColor = Colors.blue,
    this.lineWidth = 2,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = lineColor
      ..strokeWidth = lineWidth
      ..style = PaintingStyle.stroke;

    // 绘制直线
    if (linePoints.length >= 2) {
      canvas.drawLine(linePoints[0], linePoints[1], paint);
      // 绘制箭头
      _drawArrow(canvas, linePoints[0], linePoints[1], paint);
    }
  }

  void _drawArrow(Canvas canvas, Offset start, Offset end, Paint paint) {
    const arrowSize = 10.0;
    final direction = end - start;
    final unitDir = direction.normalized;
    final perpendicular = Offset(-unitDir.dy, unitDir.dx);

    final arrowTip1 = end - unitDir * arrowSize + perpendicular * arrowSize / 2;
    final arrowTip2 = end - unitDir * arrowSize - perpendicular * arrowSize / 2;

    final arrowPath = Path()
      ..moveTo(end.dx, end.dy)
      ..lineTo(arrowTip1.dx, arrowTip1.dy)
      ..lineTo(arrowTip2.dx, arrowTip2.dy)
      ..close();
    canvas.drawPath(arrowPath, paint);
  }

  @override
  bool shouldRepaint(covariant ConnectionPainter oldDelegate) {
    return oldDelegate.linePoints != linePoints;
  }
}

// 页面布局示例
Stack(
  children: [
    // 工作流容器1
    Positioned(
      left: 50,
      top: 50,
      child: Container(
        key: containerKey1,
        width: 150,
        height: 80,
        color: Colors.grey[200],
        child: const Center(child: Text("步骤1")),
      ),
    ),
    // 工作流容器2
    Positioned(
      left: 300,
      top: 50,
      child: Container(
        key: containerKey2,
        width: 150,
        height: 80,
        color: Colors.grey[200],
        child: const Center(child: Text("步骤2")),
      ),
    ),
    // 连线绘制层
    CustomPaint(
      painter: ConnectionPainter(
        linePoints: [
          getContainerRightMid(containerKey1),
          getContainerRightMid(containerKey2),
        ],
      ),
      size: MediaQuery.of(context).size,
    ),
  ],
)

二、使用轻量流程图库

如果不想从零开发,可直接使用flutter_flow_chart这类专门的流程图库,它支持容器拖拽、自动连线、自定义样式,能快速搭建类似工作流界面。

三、处理动态交互

若需要支持拖拽容器后自动更新连线,可给容器套GestureDetector处理拖拽事件,实时更新Positioned的位置参数,并在setState中刷新连线的坐标,触发CustomPainter重绘。

内容的提问来源于stack exchange,提问作者Isy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:49:59