Flutter中如何为Fl Chart左侧添加自定义值/非等间隔标题标签?
解决Fl Chart折线图左侧Y轴自定义非等间隔标签问题
我正在学习Flutter,想在Fl Chart的折线图左侧Y轴添加自定义非等间隔的标签。目前我的折线图已添加了Y值为17、18.5、25、27的参考线,但默认的interval参数要求等间隔,无法满足我在这些特定Y值位置显示对应标签的需求,希望实现对应参考线位置显示标签的效果。
当前代码如下:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class IMTLineChart extends StatelessWidget { final List<double> imtValues; final List<Timestamp> dates; IMTLineChart(this.imtValues, this.dates); LineChartBarData garis(double value, Color warna) { return LineChartBarData( spots: [FlSpot(0, value), FlSpot(imtValues.length - 1, value)], isCurved: false, color: warna, barWidth: 2, dotData: FlDotData(show: false), ); } @override Widget build(BuildContext context) { // Balikkan urutan data List<double> reversedIMTValues = imtValues.reversed.toList(); List<Timestamp> reversedDates = dates.reversed.toList(); // Buat objek DateFormat untuk mengubah format tanggal final dateFormat = DateFormat('dd-MM-yyyy'); Size size = MediaQuery.of(context).size; return LineChart( LineChartData( lineBarsData: [ LineChartBarData( spots: [ for (int i = 0; i < reversedIMTValues.length; i++) FlSpot(i.toDouble(), double.parse(reversedIMTValues[i].toStringAsFixed(1))), ], isCurved: false, color: Colors.blue, barWidth: 5, dotData: FlDotData(show: false) ), // Sangat Kurus garis(17, Colors.red), // Kurus garis(18.5, Colors.green), // Normal garis(25, Colors.orange), // Gizi lebih garis(27, Colors.red) // Obesitas ], titlesData: FlTitlesData( // sb x bawah bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, interval: 1, // Atur interval sesuai kebutuhan Anda reservedSize: 22, getTitlesWidget: (value, meta) { return Text(dateFormat.format(reversedDates[value.toInt()].toDate()), style: TextStyle(fontSize: 12), ); // Label dimulai dari 1 }, ), ), // sb x atas topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), // sb y kiri leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), // sb y kanan rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), ), gridData: FlGridData(show: false), borderData: FlBorderData(show: true), lineTouchData: LineTouchData(enabled: false), ), ); } }
实现思路
Fl Chart的SideTitles支持通过getTitlesWidget自定义标签内容,无需依赖interval的等间隔限制。核心逻辑:
- 定义需要显示的Y轴标签值列表(对应参考线的值:17、18.5、25、27)
- 在
leftTitles的getTitlesWidget中,判断当前Y轴值是否在目标列表中,仅对匹配的值返回标签文本,其余情况返回空Widget
修改后的完整代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class IMTLineChart extends StatelessWidget { final List<double> imtValues; final List<Timestamp> dates; // 定义需要显示的Y轴标签值 final List<double> targetYValues = [17, 18.5, 25, 27]; IMTLineChart(this.imtValues, this.dates); LineChartBarData garis(double value, Color warna) { return LineChartBarData( spots: [FlSpot(0, value), FlSpot(imtValues.length - 1, value)], isCurved: false, color: warna, barWidth: 2, dotData: FlDotData(show: false), ); } @override Widget build(BuildContext context) { List<double> reversedIMTValues = imtValues.reversed.toList(); List<Timestamp> reversedDates = dates.reversed.toList(); final dateFormat = DateFormat('dd-MM-yyyy'); return LineChart( LineChartData( lineBarsData: [ LineChartBarData( spots: [ for (int i = 0; i < reversedIMTValues.length; i++) FlSpot(i.toDouble(), double.parse(reversedIMTValues[i].toStringAsFixed(1))), ], isCurved: false, color: Colors.blue, barWidth: 5, dotData: FlDotData(show: false) ), garis(17, Colors.red), garis(18.5, Colors.green), garis(25, Colors.orange), garis(27, Colors.red) ], titlesData: FlTitlesData( bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, interval: 1, reservedSize: 22, getTitlesWidget: (value, meta) { return Text( dateFormat.format(reversedDates[value.toInt()].toDate()), style: TextStyle(fontSize: 12), ); }, ), ), topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), // 修改左侧Y轴标题配置 leftTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, reservedSize: 40, // 预留足够空间显示标签 getTitlesWidget: (value, meta) { // 判断当前Y值是否在目标列表中,匹配则返回标签 if (targetYValues.contains(value)) { return Text( value.toString(), style: TextStyle(fontSize: 12), ); } // 不匹配则返回空Widget,隐藏标签 return SizedBox.shrink(); }, ), ), rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)), ), gridData: FlGridData(show: false), borderData: FlBorderData(show: true), lineTouchData: LineTouchData(enabled: false), // 设置Y轴范围,确保所有目标值都在可视范围内 minY: 16, maxY: 28, ), ); } }
关键修改点
- 新增
targetYValues列表存储需要显示的Y轴标签值 - 开启左侧Y轴的
showTitles,通过getTitlesWidget筛选显示目标值的标签 - 设置
minY和maxY确保所有参考线和标签都在图表可视范围内 - 调整
reservedSize预留足够空间显示Y轴标签
内容的提问来源于stack exchange,提问作者Ilmam
相关产品推荐
相关产品推荐

