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

Flutter中为Fl_chart饼图添加Tooltip的问题求助

解决FlChart饼图悬停Tooltip位置错误的问题

方案一:使用FlChart内置Tooltip(推荐,无需手动处理坐标)

FlChart的PieChart本身提供了内置的Tooltip支持,能自动定位到触摸的饼块附近,避免坐标偏移问题。只需配置PieTouchData中的tooltipData即可:

PieChart(
  PieChartData(
    // 饼图基础配置(数据、颜色、标题等)
    sections: [
      PieChartSectionData(value: 30, color: Colors.red, title: 'A'),
      PieChartSectionData(value: 50, color: Colors.green, title: 'B'),
      PieChartSectionData(value: 20, color: Colors.blue, title: 'C'),
    ],
    // 开启触摸交互并配置Tooltip
    touchData: PieTouchData(
      enabled: true,
      tooltipData: PieTooltipData(
        tooltipBgColor: Colors.blueGrey[900]!,
        // 自定义Tooltip显示内容
        getTooltipItem: (PieChartSectionData section, int index) {
          return PieTooltipItem(
            '数值: ${section.value.toStringAsFixed(1)}',
            const TextStyle(color: Colors.white, fontSize: 14),
          );
        },
      ),
    ),
  ),
)

这种方式由FlChart内部自动处理坐标计算,Tooltip会精准跟随触摸的饼块,无需手动调整位置。

方案二:自定义Tooltip(适配复杂样式需求)

如果需要自定义Tooltip的样式,问题通常出在坐标转换错误。可以通过Stack包裹饼图和Tooltip,结合PieTouchData的回调获取饼块的局部坐标,动态更新Tooltip位置:

class PieChartWithCustomTooltip extends StatefulWidget {
  const PieChartWithCustomTooltip({super.key});

  @override
  State<PieChartWithCustomTooltip> createState() => _PieChartWithCustomTooltipState();
}

class _PieChartWithCustomTooltipState extends State<PieChartWithCustomTooltip> {
  PieChartSectionData? _hoveredSection;
  Offset? _tooltipOffset;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        PieChart(
          PieChartData(
            sections: [
              PieChartSectionData(value: 30, color: Colors.red, title: 'A'),
              PieChartSectionData(value: 50, color: Colors.green, title: 'B'),
              PieChartSectionData(value: 20, color: Colors.blue, title: 'C'),
            ],
            touchData: PieTouchData(
              enabled: true,
              touchCallback: (FlTouchEvent event, pieTouchResponse) {
                setState(() {
                  // 处理触摸按下/滑动事件
                  if (event is FlTapDownEvent || event is FlPanUpdateEvent) {
                    if (pieTouchResponse?.touchedSection != null) {
                      _hoveredSection = pieTouchResponse!.touchedSection!;
                      // 用饼块的中心坐标作为Tooltip的基准位置(偏移避免遮挡)
                      final sectionCenter = pieTouchResponse.touchedSection!.center;
                      _tooltipOffset = Offset(sectionCenter.dx + 10, sectionCenter.dy - 20);
                    } else {
                      _hoveredSection = null;
                      _tooltipOffset = null;
                    }
                  }
                  // 处理触摸抬起/结束事件
                  else if (event is FlTapUpEvent || event is FlPanEndEvent) {
                    _hoveredSection = null;
                    _tooltipOffset = null;
                  }
                });
              },
            ),
          ),
        ),
        // 显示自定义Tooltip
        if (_hoveredSection != null && _tooltipOffset != null)
          Positioned(
            left: _tooltipOffset!.dx,
            top: _tooltipOffset!.dy,
            child: Container(
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
              decoration: BoxDecoration(
                color: Colors.black.withOpacity(0.8),
                borderRadius: BorderRadius.circular(8),
              ),
              child: Text(
                '数值: ${_hoveredSection!.value.toStringAsFixed(1)}',
                style: const TextStyle(color: Colors.white, fontSize: 14),
              ),
            ),
          ),
      ],
    );
  }
}

关键注意点

  • 必须开启PieTouchData.enabled = true,否则无法触发触摸交互
  • 自定义Tooltip时,不要使用屏幕全局坐标,直接使用饼块的center属性(这是饼图组件内的相对坐标)
  • 内置Tooltip可以通过PieTooltipData的tooltipRadius、margin等属性微调位置

内容的提问来源于stack exchange,提问作者Joseph Tolulope Mofoluku

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 12:02:52