如何实现Fl_charts中多折线图的Tooltip同步显示?
实现Fl_charts多折线图联动Tooltip方案
核心思路是通过共享状态管理当前悬停的数据点索引,让所有图表根据这个索引同步显示对应位置的Tooltip。具体实现步骤如下:
1. 定义共享状态
在StatefulWidget的状态类中,声明变量保存当前悬停的索引:
int? _hoveredIndex;
2. 配置图表触摸回调
为每个LineChart的lineTouchData添加自定义触摸逻辑,用于更新共享索引:
LineTouchData( touchCallback: (FlTouchEvent event, LineTouchResponse? response) { if (event is PointerHoverEvent) { // 获取当前悬停点的X轴索引 final touchedSpot = response?.lineBarSpots?.first; if (touchedSpot != null) { setState(() { _hoveredIndex = touchedSpot.spotIndex; }); } } else if (event is PointerExitEvent) { // 鼠标离开时重置索引 setState(() { _hoveredIndex = null; }); } }, // 关闭默认Tooltip触发逻辑,改为手动控制 enabled: false, // 自定义Tooltip显示规则 getTooltipItems: (List<LineBarSpot> spots) { // 仅当共享索引匹配时返回Tooltip内容 if (spots.isNotEmpty && spots.first.spotIndex == _hoveredIndex) { return [ LineTooltipItem( '数值: ${spots.first.y.toStringAsFixed(2)}', const TextStyle(color: Colors.white), ) ]; } return []; }, )
3. 同步所有图表Tooltip
所有折线图都使用上述LineTouchData配置,这样任意一个图表触发索引更新时,其余图表会自动根据共享索引显示对应位置的Tooltip。
完整示例代码片段
class LinkedTooltipCharts extends StatefulWidget { const LinkedTooltipCharts({super.key}); @override State<LinkedTooltipCharts> createState() => _LinkedTooltipChartsState(); } class _LinkedTooltipChartsState extends State<LinkedTooltipCharts> { int? _hoveredIndex; // 模拟4组长度一致的测试数据 final List<List<FlSpot>> _chartData = [ List.generate(10, (i) => FlSpot(i.toDouble(), (i * 2).toDouble())), List.generate(10, (i) => FlSpot(i.toDouble(), (i * 3).toDouble())), List.generate(10, (i) => FlSpot(i.toDouble(), (i * 1.5).toDouble())), List.generate(10, (i) => FlSpot(i.toDouble(), (i * 2.5).toDouble())), ]; Widget _buildChart(List<FlSpot> data) { return LineChart( LineChartData( lineTouchData: LineTouchData( touchCallback: (FlTouchEvent event, LineTouchResponse? response) { if (event is PointerHoverEvent) { final touchedSpot = response?.lineBarSpots?.first; if (touchedSpot != null) { setState(() { _hoveredIndex = touchedSpot.spotIndex; }); } } else if (event is PointerExitEvent) { setState(() { _hoveredIndex = null; }); } }, enabled: false, getTooltipItems: (List<LineBarSpot> spots) { if (spots.isNotEmpty && spots.first.spotIndex == _hoveredIndex) { return [ LineTooltipItem( '${spots.first.y.toStringAsFixed(2)}', const TextStyle(color: Colors.white, fontSize: 12), ) ]; } return []; }, ), gridData: const FlGridData(show: true), titlesData: const FlTitlesData(show: true), borderData: FlBorderData(show: true), lineBarsData: [ LineChartBarData( spots: data, isCurved: true, color: Colors.blue, dotData: const FlDotData(show: true), ), ], ), ); } @override Widget build(BuildContext context) { return GridView.count( crossAxisCount: 2, children: _chartData.map((data) => _buildChart(data)).toList(), ); } }
关键注意事项
- 必须保证所有图表的X轴数据索引完全对应,否则会出现Tooltip错位
- 若单图表包含多个数据系列,需在
getTooltipItems中遍历所有系列的对应索引点,生成多个Tooltip条目 - 可根据需求调整
PointerExitEvent的处理逻辑,比如添加延迟重置,避免鼠标在图表间移动时Tooltip频繁消失
内容的提问来源于stack exchange,提问作者Mauro Gentile
相关产品推荐
相关产品推荐

