flutterdartfl-chart

How to show date on bottomTitle in fl_chart


So I'm having a hard time figuring out how to show the date I'm getting from my PHP Script into FlChart.

The data I get from my PHP Script looks like this, so basically what this means is that I get an average value on the day it was measured on.

[
  {
    "Datum": "Sun",
    "Avg": 166
  },
  {
    "Datum": "Mon",
    "Avg": 333
  },
  {
    "Datum": "Sat",
    "Avg": 123
  }
]

My class looks like this

class AvgDataBaseData {
  final int? avg;
  final String? date;
  AvgDataBaseData({this.avg, this.date});
  factory AvgDataBaseData.fromJson(Map<String, dynamic> json) {
    return AvgDataBaseData(avg: json['Avg'], date: json['Datum']);
  }
}

Code to show my line-chart

class AvgDataBaseList extends StatelessWidget {
  const AvgDataBaseList({super.key, required this.AvgDataBases});
  final List<AvgDataBaseData> AvgDataBases;

  @override
  Widget build(BuildContext context) {
    List<FlSpot> spots = AvgDataBases.asMap().entries.map((e) {
      return FlSpot(e.key.toDouble(), e.value.avg!.toDouble());
    }).toList();

    SideTitles _bottomTitles() {
      return SideTitles(
        showTitles: true,
        getTitlesWidget: (value, meta) {
          var date = AvgDataBases.asMap().entries.map((e) => Text(e.value.date.toString()),).toList();
          return SideTitleWidget(axisSide: meta.axisSide, child: Text(date.toString()));
        },
      );
    }

    return Container(
        margin: const EdgeInsets.symmetric(horizontal: 50),
        child: LineChart(LineChartData(
          borderData: borderData,
          titlesData: FlTitlesData(
            show: true,
            bottomTitles: AxisTitles(
              sideTitles: _bottomTitles(),
            ),
            leftTitles: AxisTitles(
              sideTitles: SideTitles(showTitles: false),
            ),
            topTitles: AxisTitles(
              sideTitles: SideTitles(showTitles: false),
            ),
            rightTitles: AxisTitles(
              sideTitles: SideTitles(showTitles: false),
            ),
          ),
          lineBarsData: [
            LineChartBarData(
                barWidth: 5,
                spots: spots,
                isCurved: true,
                gradient: LinearGradient(colors: gradientColors),
                belowBarData: BarAreaData(
                    show: true,
                    gradient: LinearGradient(
                      colors: gradientColors
                          .map((color) => color.withOpacity(0.3))
                          .toList(),
                    )))
          ],
          //to deactive the grid
          gridData: gridData,
          //titlesData: titlesData)),
          // titlesData: FlTitlesData(
          //     rightTitles: AxisTitles(
          //       sideTitles: SideTitles(
          //         showTitles: true,
          //         reservedSize: 40,
          //       ),
          //     ),
          //     show: false))),
        )));
  }
}

I'm able to show the average value in my linechart, but I'm unable to show the date the average value was measured on. I tried returning the SideTitleWidget like this

SideTitles _bottomTitles() {
      return SideTitles(
        showTitles: true,
        getTitlesWidget: (value, meta) {
          var date = AvgDataBases.asMap().entries.map((e) => Text(e.value.date.toString()),).toList();
          return SideTitleWidget(axisSide: meta.axisSide, child: Text(date.toString()));
        },
      );
    }

but this doesn't work like i want it.


Solution

  • Firstly, you need to provide some theses parameters

     LineChartData(
              minX: 0,
              maxX: AvgDataBases.length.toDouble(),
              minY: 0,
              maxY: maxY.toDouble(),
    

    And bottomTitles will be

        SideTitles _bottomTitles() {
          return SideTitles(
            showTitles: true,
            interval: 1,
            getTitlesWidget: (value, meta) {
              var date = value.toInt() < AvgDataBases.length
                  ? AvgDataBases[value.toInt()].date
                  : "";
              return SideTitleWidget(axisSide: meta.axisSide, child: Text("$date"));
            },
          );
        }
    

    Test snippet

    class AvgDataBaseList extends StatelessWidget {
      // const AvgDataBaseList({super.key, required this.AvgDataBases});
      final List<AvgDataBaseData> AvgDataBases = [
        AvgDataBaseData(avg: 166, date: "Sun"),
        AvgDataBaseData(avg: 333, date: "Mon"),
        AvgDataBaseData(avg: 123, date: "Sat"),
      ];
    
      late final maxY = AvgDataBases.map((e) => e.avg ?? 0).toList().reduce(max); // import dart:math
      @override
      Widget build(BuildContext context) {
        List<FlSpot> spots = AvgDataBases.asMap().entries.map((e) {
          return FlSpot(e.key.toDouble(), e.value.avg!.toDouble());
        }).toList();
    
        SideTitles _bottomTitles() {
          return SideTitles(
            showTitles: true,
            interval: 1,
            getTitlesWidget: (value, meta) {
              var date = value.toInt() < AvgDataBases.length
                  ? AvgDataBases[value.toInt()].date
                  : "";
              return SideTitleWidget(axisSide: meta.axisSide, child: Text("$date"));
            },
          );
        }
    
        return Container(
            margin: const EdgeInsets.symmetric(horizontal: 50),
            child: LineChart(LineChartData(
              minX: 0,
              maxX: AvgDataBases.length.toDouble(),
              minY: 0,
              maxY: maxY.toDouble(),
              baselineX: 4,
              titlesData: FlTitlesData(
                show: true,
                bottomTitles: AxisTitles(
                  sideTitles: _bottomTitles(),
                ),
                leftTitles: AxisTitles(
                  sideTitles: SideTitles(showTitles: false),
                ),
                topTitles: AxisTitles(
                  sideTitles: SideTitles(showTitles: false),
                ),
                rightTitles: AxisTitles(
                  sideTitles: SideTitles(showTitles: false),
                ),
              ),
              lineBarsData: [
                LineChartBarData(
                  barWidth: 5,
                  spots: spots,
                  isCurved: true,
                  belowBarData: BarAreaData(
                    show: true,
                  ),
                )
              ],
            )));
      }
    }
    

    enter image description here