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

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的等间隔限制。核心逻辑:

  1. 定义需要显示的Y轴标签值列表(对应参考线的值:17、18.5、25、27)
  2. 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:12:19