Chromacry
Chromacry

Reputation: 36

FL_Charts bottomtitle overlapping each other on small screens. How to fix?

I'm new to flutter and am having issues with flutter FL_Charts. I've looked at their documentation and tried change the bottomTiles but the txt will overlap one another on small screens.

Ideally, I would want to add horizontal scroll as I'll be inserting data dynamically.

Current Output

My Current Code:

import 'package:fl_chart/fl_chart.dart';

class WaterUsageBarChart extends StatefulWidget {
  WaterUsageBarChart({super.key});

  final Color? leftBarColor = Colors.yellow[200];
  final Color? rightBarColor = Colors.red[200];
  final Color? avgColor = Colors.orange;

  @override
  State<WaterUsageBarChart> createState() => _WaterUsageBarChartState();
}

class _WaterUsageBarChartState extends State<WaterUsageBarChart> {
  final double width = 7;

  late List<BarChartGroupData> rawBarGroups;
  late List<BarChartGroupData> showingBarGroups;

  int touchedGroupIndex = -1;

  @override
  void initState() {
    super.initState();
    //* Amount of bar in chart
    //* makeGroupData(Grouping, Bar1, Bar2)
    final barGroup1 = makeGroupData(0, 0, 2);
    final barGroup2 = makeGroupData(1, 20, 20);
    final barGroup3 = makeGroupData(2, 5, 5);
    final barGroup4 = makeGroupData(3, 5, 16);
    final barGroup5 = makeGroupData(4, 7, 6);
    final barGroup6 = makeGroupData(5, 1000, 900);
    final barGroup7 = makeGroupData(6, 10, 1.5);

    final items = [
      barGroup1,
      barGroup2,
      barGroup3,
      barGroup4,
      barGroup5,
      barGroup6,
      barGroup7,
    ];

    rawBarGroups = items;

    showingBarGroups = rawBarGroups;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 300,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              // makeTransactionsIcon(),
              const Icon(Icons.water_drop_rounded, color: Colors.white),
              const SizedBox(
                width: 38,
              ),
              Column(
                children: const [
                  Text(
                    'Average Water Usage',
                    style: TextStyle(color: Colors.white, fontSize: 20),
                  ),
                  SizedBox(
                    width: 8,
                  ),
                  Text(
                    'per month',
                    style: TextStyle(
                      color: Color(0xff77839a),
                      fontSize: 16,
                    ),
                  ),
                ],
              ),
            ],
          ),
          const SizedBox(
            height: 38,
          ),
          Expanded(
            child: Container(
              child: BarChart(
                  BarChartData(
                    maxY: 5000,
                    barTouchData: BarTouchData(
                      touchTooltipData: BarTouchTooltipData(
                        tooltipBgColor: Colors.grey,
                        getTooltipItem: (a, b, c, d) => null,
                      ),
                      touchCallback: (FlTouchEvent event, response) {
                        if (response == null || response.spot == null) {
                          setState(() {
                            touchedGroupIndex = -1;
                            showingBarGroups = List.of(rawBarGroups);
                          });
                          return;
                        }
              
                        touchedGroupIndex = response.spot!.touchedBarGroupIndex;
              
                        setState(() {
                          if (!event.isInterestedForInteractions) {
                            touchedGroupIndex = -1;
                            showingBarGroups = List.of(rawBarGroups);
                            return;
                          }
                          showingBarGroups = List.of(rawBarGroups);
                          if (touchedGroupIndex != -1) {
                            var sum = 0.0;
                            for (final rod
                                in showingBarGroups[touchedGroupIndex].barRods) {
                              sum += rod.toY;
                            }
                            final avg = sum /
                                showingBarGroups[touchedGroupIndex]
                                    .barRods
                                    .length;
              
                            showingBarGroups[touchedGroupIndex] =
                                showingBarGroups[touchedGroupIndex].copyWith(
                              barRods: showingBarGroups[touchedGroupIndex]
                                  .barRods
                                  .map((rod) {
                                return rod.copyWith(
                                    toY: avg, color: widget.avgColor);
                              }).toList(),
                            );
                          }
                        });
                      },
                    ),
                    titlesData: FlTitlesData(
                      show: true,
                      rightTitles: AxisTitles(
                        sideTitles: SideTitles(showTitles: false),
                      ),
                      topTitles: AxisTitles(
                        sideTitles: SideTitles(showTitles: false),
                      ),
                      bottomTitles: AxisTitles(
                        sideTitles: SideTitles(
                          showTitles: true,
                          getTitlesWidget: bottomTitles,
                          reservedSize: 42,
                        ),
                      ),
                      leftTitles: AxisTitles(
                        sideTitles: SideTitles(
                          showTitles: true,
                          reservedSize: 28,
                          interval: 1,
                          getTitlesWidget: leftTitles,
                        ),
                      ),
                    ),
                    borderData: FlBorderData(
                      show: false,
                    ),
                    barGroups: showingBarGroups,
                    gridData: FlGridData(show: false),
                  ),
                ),
            ),
            ),
          // const SizedBox(
          //   height: 12,
          // ),
        ],
      ),
    );
  }

  //* Data
  Widget leftTitles(double value, TitleMeta meta) {
    const style = TextStyle(
      color: Color(0xff7589a2),
      fontWeight: FontWeight.bold,
      fontSize: 14,
    );
    String text;
    if (value == 0) {
      text = '1K';
    } else if (value == 5) {
      text = '5K';
    } else if (value == 5000) {
      text = '5K';
    } else {
      return Container();
    }
    return SideTitleWidget(
      axisSide: meta.axisSide,
      space: 0,
      child: Text(text, style: style),
    );
  }

  //* By number of bars created
  Widget bottomTitles(double value, TitleMeta meta) {
    //TODO Dynamically create titles from data
    final titles = <String>['22 Feb', '23 Feb', '24 Feb', '25 Feb', '26 Feb', '27 Feb', '28 Feb'];

    final intIndex = value.isFinite ? value.toInt() : 0;
    final title = intIndex >= 0 && intIndex < titles.length ? titles[intIndex] : '';

    final Widget text = Text(
      // titles[value.toInt()], // Original code
      title,
      style: const TextStyle(
        color: Color(0xff7589a2),
        fontWeight: FontWeight.bold,
        fontSize: 14,
      ),
    );

    return SideTitleWidget(
      axisSide: meta.axisSide,
      space: 16, //16 //margin top
      child: text,
    );
  }

  BarChartGroupData makeGroupData(int x, double y1, double y2) {
    return BarChartGroupData(
      barsSpace: 4, //4
      x: x,
      barRods: [
        BarChartRodData(
          toY: y1,
          color: widget.leftBarColor,
          width: width,
        ),
        BarChartRodData(
          toY: y2,
          color: widget.rightBarColor,
          width: width,
        ),
      ],
    );
  }
}

After Adding Horizontal Scroll Widget I've tried to add horizontal scroll and it has render issues but I'm unable to solve. It seem to have render issues. I've also tried to add height: 300 to attempt to solve the Infinity or NaN. Please help thanks.

HorizontalScroll Output

Error: ═╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ The following UnsupportedError was thrown building SideTitlesWidget(dirty): Unsupported operation: Infinity or NaN toInt

The relevant error-causing widget was: SideTitlesWidget

Upvotes: 1

Views: 584

Answers (1)

Sjonnie2nd
Sjonnie2nd

Reputation: 31

A bit late but..

I ran into your last error with fl_chart: "SideTitlesWidget(dirty): Unsupported operation: Infinity or NaN toInt".

In my case it was solved by an Expanded() around the chart. Did you miss that somewhere?

Upvotes: 0

Related Questions