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

如何使用Flutter的graphview包动态切换线条样式?

用Flutter GraphView包动态切换线条绘制样式

要实现线条在实线、点线、虚线间动态切换,核心是自定义边的绘制逻辑,结合Flutter状态管理实时更新绘制参数。以下是具体实现步骤:

1. 定义线条样式枚举

先创建枚举统一管理三种线条状态,避免硬编码:

enum LineStyle {
  solid,
  dotted,
  dashed,
}

2. 自定义边绘制器(EdgePainter)

GraphView允许通过EdgePainter自定义边的绘制,我们在这个类中根据当前样式设置不同的Paint参数:

class CustomEdgePainter extends EdgePainter {
  final LineStyle currentStyle;

  CustomEdgePainter({required this.currentStyle});

  @override
  void paint(
      Canvas canvas,
      Size size,
      Animation<double> animation,
      Edge edge,
      Node parentNode,
      Node childNode,
      Graph graph,
      RenderBox parentBox,
      RenderBox childBox,
      bool isFocused,
      bool isHovered) {
    final paint = Paint()
      ..color = Colors.blue
      ..strokeWidth = 2.0
      ..style = PaintingStyle.stroke;

    // 根据样式设置 dashPattern
    switch (currentStyle) {
      case LineStyle.solid:
        paint.pathEffect = null;
        break;
      case LineStyle.dotted:
        paint.pathEffect = PathEffect.dashPattern([2, 4]); // 短实线+长间隔
        break;
      case LineStyle.dashed:
        paint.pathEffect = PathEffect.dashPattern([8, 4]); // 长实线+短间隔
        break;
    }

    // 绘制默认边路径(也可自定义路径)
    final path = getPath(size, edge, parentBox, childBox);
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomEdgePainter oldDelegate) {
    return oldDelegate.currentStyle != currentStyle; // 样式变化时才重绘
  }
}

3. 在StatefulWidget中集成并动态切换

创建StatefulWidget维护当前线条样式,将自定义CustomEdgePainter传入GraphView配置:

class DynamicLineGraph extends StatefulWidget {
  @override
  _DynamicLineGraphState createState() => _DynamicLineGraphState();
}

class _DynamicLineGraphState extends State<DynamicLineGraph> {
  late LineStyle _currentLineStyle;
  final Graph graph = Graph()..isTree = true;
  final BuchheimWalkerConfiguration config = BuchheimWalkerConfiguration();

  @override
  void initState() {
    super.initState();
    _currentLineStyle = LineStyle.solid;
    // 初始化示例节点
    final node1 = Node.Id("Node 1");
    final node2 = Node.Id("Node 2");
    final node3 = Node.Id("Node 3");
    graph.addEdge(node1, node2);
    graph.addEdge(node1, node3);

    config
      ..siblingSeparation = 100
      ..levelSeparation = 150
      ..subtreeSeparation = 150
      ..orientation = BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM;
  }

  void _toggleLineStyle() {
    setState(() {
      // 循环切换三种样式
      _currentLineStyle = _currentLineStyle == LineStyle.solid
          ? LineStyle.dotted
          : _currentLineStyle == LineStyle.dotted
              ? LineStyle.dashed
              : LineStyle.solid;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: _toggleLineStyle,
          child: Text("切换线条样式:${_currentLineStyle.name}"),
        ),
        Expanded(
          child: GraphView(
            graph: graph,
            algorithm: BuchheimWalkerAlgorithm(config),
            edgePainter: CustomEdgePainter(currentStyle: _currentLineStyle),
            nodeBuilder: (Node node) {
              return Container(
                padding: EdgeInsets.all(16),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [BoxShadow(blurRadius: 2)],
                ),
                child: Text(node.id),
              );
            },
          ),
        ),
      ],
    );
  }
}

关键说明

  • PathEffect.dashPattern:数组元素依次控制实线长度、间隔长度,循环重复形成对应线条样式。
  • shouldRepaint:重写该方法确保仅当样式变化时触发重绘,优化性能。
  • 状态更新:通过setState切换样式后,GraphView会自动使用新的绘制参数刷新所有边。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 05:20:51