flutteruser-interfacechartsflutter-charts

Flutter fl_chart: Adding formatted date as tilted labels on X axis


I am using fl_chart package in my Flutter application to add a Bar chart that is supposed to display dates (format - dd/mm/yy) in a titled fashion in the X - axis as shown in the below image

Current UI state

The code which generates this UI is as follows

import 'dart:math';

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:vendors/gen/colors.gen.dart';
import 'package:vendors/src/shared/widgets/dividers/custom_divider.dart';
import 'package:vendors/src/shared/widgets/input/input_date_field.dart';

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

  @override
  State<ClaimsChart> createState() => _ClaimsChartState();
}

class _ClaimsChartState extends State<ClaimsChart> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12.0),
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
          AspectRatio(
            aspectRatio: 1.75,
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 4.0),
              child: BarChart(
                BarChartData(
                  barGroups: _chartGroups(),
                  borderData: FlBorderData(
                      border: const Border(
                          bottom: BorderSide(color: Colors.black26),
                          left: BorderSide(color: Colors.black26))),
                  gridData: const FlGridData(show: false),
                  titlesData: FlTitlesData(
                    bottomTitles: AxisTitles(sideTitles: _bottomTitles),
                    leftTitles: AxisTitles(
                        sideTitles: SideTitles(
                            showTitles: true,
                            interval: 5,
                            reservedSize: 20,
                            getTitlesWidget: (value, meta) => Text(
                                  value.toInt().toString(),
                                  style: TextStyle(
                                      color: Colors.black.withOpacity(0.6),
                                      fontSize: 12),
                                ))),
                    topTitles: const AxisTitles(
                        sideTitles: SideTitles(showTitles: false)),
                    rightTitles: const AxisTitles(
                        sideTitles: SideTitles(showTitles: false)),
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }

  List<BarChartGroupData> _chartGroups() {
    return List.generate(
            10,
            (index) =>
                ChartData(date: DateTime.now(), value: Random().nextInt(20)))
        .map((point) =>
            BarChartGroupData(x: point.date.microsecondsSinceEpoch, barRods: [
              BarChartRodData(
                  toY: point.value.toDouble(),
                  color: ColorName.barChart,
                  width: 12,
                  borderRadius: BorderRadius.circular(0)),
            ]))
        .toList();
  }

  SideTitles get _bottomTitles => SideTitles(
        showTitles: true,
        getTitlesWidget: (value, meta) {
          String formattedDate = DateFormat("dd/mm/yy")
              .format(DateTime.fromMicrosecondsSinceEpoch(value.toInt()));
          return SideTitleWidget(
              axisSide: meta.axisSide,
              // You can adjust the space as needed
              child: Transform.rotate(
                angle: -45 * (pi / 180),
                // Rotate by 45 degrees (convert to radians)
                alignment: Alignment.bottomLeft,
                child: Padding(
                  padding: const EdgeInsets.only(top: 0.0),
                  child: Text(
                    formattedDate,
                    textAlign: TextAlign.left,
                    style: TextStyle(
                      color: Colors.black.withOpacity(0.6),
                      fontSize: 12,
                    ),
                  ),
                ),
              ));
        },
      );
}

class ChartData {
  final DateTime date;
  final int value;

  ChartData({required this.date, this.value = 9});
}

Note - The ClaimsChart widget is part of a SingleChildScrollView

The expected UI should be like this

enter image description here

I have tried to add Top padding to move the Text title widget down by 10 points, but it just made the Text disappear


Solution

  • There is no need of Transform.rotate if you only want to rotate the formatted date text. There is an angle property in SideTitleWidget that can help you out. Code snippet for your reference :-

         SideTitleWidget(
            axisSide: meta.axisSide,
            angle: 125,
            child: Text(
              formattedDate,
              textAlign: TextAlign.left,
              style: TextStyle(
                color: Colors.black.withOpacity(0.6),
                fontSize: 12,
              ),
            ),
          )
    

    Let me know if it helps.