fl_chart icon indicating copy to clipboard operation
fl_chart copied to clipboard

chart only shows after clicked or tapped

Open mickykro opened this issue 3 years ago • 2 comments

I enter the page where the chart supposed to show, but it shows only when i click on it. WhatsApp Image 2021-12-20 at 16 00 57 Screen Shot 2021-12-20 at 15 51 32

mickykro avatar Dec 20 '21 14:12 mickykro

@imaNNeoFighT

mickykro avatar Dec 20 '21 15:12 mickykro

Hi @mickykro. Can you please check it with the latest version?

imaNNeo avatar Feb 14 '22 19:02 imaNNeo

I have the same problem now on the some devices. The graph line is only visible when you click on the graph itself - the points are always visible

Fudal avatar Jun 09 '23 15:06 Fudal

Can you please give me a reproducible code? (a main.dart file content)

imaNNeo avatar Jun 10 '23 14:06 imaNNeo

@imaNNeo

That is my chart file:

import 'dart:math';

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:package_name/domain/chart/chart_time_period.dart';
import 'package:package_name/extensions/context_extension.dart';
import 'package:package_name/style/app_colors.dart';
import 'package:package_name/style/dimens.dart';

class PackageChartTile extends StatelessWidget {
  final Map<DateTime, double> aggregatedChartData;
  final ChartTimePeriod selectedTimePeriod;
  final Set<double> leftTitlesSet = {};

  PackageChartTile(this.aggregatedChartData, this.selectedTimePeriod);

  @override
  Widget build(BuildContext context) {
    final List<Color> gradientColors = [AppColors.shakespeare, AppColors.aphroditeAqua];

    double minY = 0;
    double maxY = 0;
    double maxX = 11;

    if (aggregatedChartData.isNotEmpty) {
      minY = aggregatedChartData.values.reduce(min);
      maxY = aggregatedChartData.values.reduce(max);
      final double padding = (maxY - minY) * 0.2;
      minY -= padding;
      maxY += padding;
      maxX = aggregatedChartData.length.toDouble() - 1;
    }

    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Container(
        width: _getChartWidth(),
        height: 210,
        padding: const EdgeInsets.only(top: Dimens.spacingM, right: Dimens.spacingM),
        child: LineChart(
          LineChartData(
            gridData: FlGridData(
              show: true,
              drawVerticalLine: false,
              horizontalInterval: ((maxY - minY) / 7) <= 0 ? 1 : ((maxY - minY) / 7),
              getDrawingHorizontalLine: (value) {
                return FlLine(
                  color: AppColors.lightSilver,
                  strokeWidth: 1,
                );
              },
            ),
            // lineTouchData: LineTouchData(
            //   touchCallback: (_, __) {},
            //   touchTooltipData: LineTouchTooltipData(
            //     tooltipBgColor: AppColors.aeroBlue,
            //     tooltipMargin: Dimens.spacingM,
            //     getTooltipItems: (List<LineBarSpot> touchedBarSpots) {
            //       return touchedBarSpots.map((barSpot) {
            //         final flSpot = barSpot;
            //         final DateTime date = aggregatedChartData.keys.elementAt(flSpot.x.toInt());
            //         return LineTooltipItem(
            //           '${DateFormat.MMM().format(date)}: ${flSpot.y.toStringAsFixed(1)}',
            //           context.typo.body3.shakespeare().copyWith(),
            //         );
            //       }).toList();
            //     },
            //   ),
            // ),
            titlesData: FlTitlesData(
              show: true,
              rightTitles: AxisTitles(
                sideTitles: SideTitles(
                  showTitles: true,
                  reservedSize: 35,
                  interval: ((maxY - minY) / 7) <= 0 ? 1 : ((maxY - minY) / 7),
                  getTitlesWidget: (double value, TitleMeta meta) {
                    return SideTitleWidget(
                      axisSide: AxisSide.bottom,
                      child: Text(
                        double.tryParse(meta.formattedValue) == minY || double.tryParse(meta.formattedValue) == maxY
                            ? ''
                            : meta.formattedValue,
                        style: context.typo.body4,
                        textAlign: TextAlign.left,
                      ),
                    );
                  },
                ),
              ),
              topTitles: AxisTitles(
                sideTitles: SideTitles(showTitles: false),
              ),
              bottomTitles: AxisTitles(
                sideTitles: SideTitles(
                  showTitles: true,
                  reservedSize: 30,
                  interval: 1,
                  getTitlesWidget: (double value, TitleMeta meta) {
                    final DateTime date = aggregatedChartData.isNotEmpty && value.toInt() < aggregatedChartData.length
                        ? aggregatedChartData.keys.elementAt(value.toInt())
                        : DateTime.now();
                    return SideTitleWidget(
                      axisSide: AxisSide.bottom,
                      child: Text(
                        _bottomTileText(date),
                        style: context.typo.body4,
                        textAlign: TextAlign.left,
                      ),
                    );
                  },
                ),
              ),
              leftTitles: AxisTitles(
                sideTitles: SideTitles(
                  showTitles: true,
                  reservedSize: 30,
                  interval: ((maxY - minY) / 7) <= 0 ? 1 : ((maxY - minY) / 7),
                  getTitlesWidget: (double value, TitleMeta meta) {
                    return SideTitleWidget(
                      axisSide: AxisSide.bottom,
                      child: Text(
                        double.tryParse(meta.formattedValue) == minY || double.tryParse(meta.formattedValue) == maxY
                            ? ''
                            : meta.formattedValue,
                        style: context.typo.body4,
                        textAlign: TextAlign.left,
                      ),
                    );
                  },
                ),
              ),
            ),
            borderData: FlBorderData(show: false),
            minX: 0,
            maxX: maxX,
            minY: minY,
            maxY: maxY,
            lineBarsData: [
              LineChartBarData(
                spots: _generateFlSpots(),
                isCurved: true,
                barWidth: 2,
                isStrokeCapRound: true,
                dotData: FlDotData(
                  show: true,
                ),
                belowBarData: BarAreaData(
                  show: true,
                  gradient: LinearGradient(
                    colors: gradientColors.map((color) => color.withOpacity(0.2)).toList(),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  List<FlSpot> _generateFlSpots() {
    final List<FlSpot> flSpots = [];

    int index = 0;
    for (final entry in aggregatedChartData.entries) {
      flSpots.add(FlSpot(index.toDouble(), entry.value));
      index++;
    }

    return flSpots;
  }

  String _bottomTileText(DateTime date) {
    String formatPattern;
    switch (selectedTimePeriod) {
      case ChartTimePeriod.all:
        formatPattern = 'dd.MM.yy';
        break;
      case ChartTimePeriod.week:
        formatPattern = 'dd.MM';
        break;
      case ChartTimePeriod.month:
        formatPattern = 'dd.MM';
        break;
      case ChartTimePeriod.year:
        formatPattern = 'MMM';
        break;
      case ChartTimePeriod.day:
        formatPattern = 'HH:mm';
        break;
    }
    return DateFormat(formatPattern).format(date);
  }

  double _getChartWidth() {
    if (aggregatedChartData.length <= 10) {
      return aggregatedChartData.length * 150;
    } else {
      return aggregatedChartData.length * (selectedTimePeriod == ChartTimePeriod.all ? 55 : 40);
    }
  }
}

I've commented lineTouchData for testing but with and without that lineTouchData code the user has the same effect.

https://github.com/imaNNeo/fl_chart/assets/13346676/c880f041-4036-4458-ae05-49c3ad758ad0

In my devices I don't have that problem but users on other phones gave me know about that.

Fudal avatar Jun 10 '23 16:06 Fudal

@imaNNeo any ideas?

Fudal avatar Jun 14 '23 10:06 Fudal

import 'dart:math';

import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart';

I cannot run your code, it has compile issue. image

imaNNeo avatar Jun 14 '23 18:06 imaNNeo

@imaNNeo

Okay, I've changed my code, should be better to reproducible:

import 'dart:math';

import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class PackageNameChartTile extends StatelessWidget {
  final Map<DateTime, double> aggregatedChartData;
  final Set<double> leftTitlesSet = {};

  PackageNameChartTile(this.aggregatedChartData);

  @override
  Widget build(BuildContext context) {
    final List<Color> gradientColors = [const Color(0xff418AB9), const Color(0xff50EDCB)];

    double minY = 0;
    double maxY = 0;
    double maxX = 11;

    if (aggregatedChartData.isNotEmpty) {
      minY = aggregatedChartData.values.reduce(min);
      maxY = aggregatedChartData.values.reduce(max);
      final double padding = (maxY - minY) * 0.2;
      minY -= padding;
      maxY += padding;
      maxX = aggregatedChartData.length.toDouble() - 1;
      minY = (minY - 0.1 * padding).roundToDouble(); //adjusting minY slightly
      maxY = (maxY + 0.1 * padding).roundToDouble(); //adjusting maxY slightly
    }

    final double? calculatedInterval = ((maxY - minY) / 8) <= 0
        ? 1
        : double.tryParse(((maxY - minY) / 8).toStringAsFixed(1));
    final double? verticalLabelInterval = calculatedInterval == 0 ? 1 : calculatedInterval;


    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Container(
        width: _getChartWidth(),
        height: 210,
        padding: const EdgeInsets.only(top: 16, right: 16),
        child: LineChart(
          LineChartData(
            gridData: FlGridData(
              show: true,
              drawVerticalLine: false,
              horizontalInterval: verticalLabelInterval,
              getDrawingHorizontalLine: (value) {
                return FlLine(
                  color: const Color(0xffD9D9D9),
                  strokeWidth: 1,
                );
              },
            ),
            lineTouchData: LineTouchData(
              touchCallback: (_, __) {},
              touchTooltipData: LineTouchTooltipData(
                tooltipBgColor: const Color(0xffC8F9EE),
                tooltipMargin: 16,
                getTooltipItems: (List<LineBarSpot> touchedBarSpots) {
                  return touchedBarSpots.map((barSpot) {
                    final flSpot = barSpot;
                    final DateTime date = aggregatedChartData.keys.elementAt(flSpot.x.toInt());
                    return LineTooltipItem(
                      '${DateFormat.MMM().format(date)}: ${flSpot.y.toStringAsFixed(1)}',
                        const TextStyle(
                          height: 1.71,
                          fontSize: 14.0,
                          fontWeight: FontWeight.w400,
                        )
                    );
                  }).toList();
                },
              ),
            ),
            titlesData: FlTitlesData(
              show: true,
              rightTitles: AxisTitles(
                sideTitles: SideTitles(
                  showTitles: true,
                  reservedSize: 35,
                  interval: verticalLabelInterval,
                  getTitlesWidget: (double value, TitleMeta meta) {
                    return SideTitleWidget(
                      axisSide: AxisSide.bottom,
                      child: Text(
                        double.tryParse(meta.formattedValue) == minY || double.tryParse(meta.formattedValue) == maxY
                            ? ''
                            : meta.formattedValue,
                        style: const TextStyle(
                          height: 1.36,
                          fontSize: 10.0,
                          fontWeight: FontWeight.w500,
                        ),
                        textAlign: TextAlign.left,
                      ),
                    );
                  },
                ),
              ),
              topTitles: AxisTitles(
                sideTitles: SideTitles(showTitles: false),
              ),
              bottomTitles: AxisTitles(
                sideTitles: SideTitles(
                  showTitles: true,
                  reservedSize: 30,
                  interval: 1,
                  getTitlesWidget: (double value, TitleMeta meta) {
                    final DateTime date = aggregatedChartData.isNotEmpty && value.toInt() < aggregatedChartData.length
                        ? aggregatedChartData.keys.elementAt(value.toInt())
                        : DateTime.now();
                    return SideTitleWidget(
                      axisSide: AxisSide.bottom,
                      child: Text(
                        _bottomTileText(date),
                        style: const TextStyle(
                          height: 1.36,
                          fontSize: 10.0,
                          fontWeight: FontWeight.w500,
                        ),
                        textAlign: TextAlign.left,
                      ),
                    );
                  },
                ),
              ),
              leftTitles: AxisTitles(
                sideTitles: SideTitles(
                  showTitles: true,
                  reservedSize: 30,
                  interval: verticalLabelInterval,
                  getTitlesWidget: (double value, TitleMeta meta) {
                    return SideTitleWidget(
                      axisSide: AxisSide.bottom,
                      child: Text(
                        double.tryParse(meta.formattedValue) == minY || double.tryParse(meta.formattedValue) == maxY
                            ? ''
                            : meta.formattedValue,
                        style: const TextStyle(
                          height: 1.36,
                          fontSize: 10.0,
                          fontWeight: FontWeight.w500,
                        ),
                        textAlign: TextAlign.left,
                      ),
                    );
                  },
                ),
              ),
            ),
            borderData: FlBorderData(show: false),
            minX: 0,
            maxX: maxX,
            minY: minY,
            maxY: maxY,
            lineBarsData: [
              LineChartBarData(
                spots: _generateFlSpots(),
                isCurved: true,
                barWidth: 2,
                isStrokeCapRound: true,
                dotData: FlDotData(
                  show: true,
                ),
                belowBarData: BarAreaData(
                  show: true,
                  gradient: LinearGradient(
                    colors: gradientColors.map((color) => color.withOpacity(0.2)).toList(),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  List<FlSpot> _generateFlSpots() {
    final List<FlSpot> flSpots = [];

    int index = 0;
    for (final entry in aggregatedChartData.entries) {
      flSpots.add(FlSpot(index.toDouble(), entry.value));
      index++;
    }

    return flSpots;
  }

  String _bottomTileText(DateTime date) {
    const String formatPattern = 'dd.MM.yy';
    return DateFormat(formatPattern).format(date);
  }

  double _getChartWidth() {
    if (aggregatedChartData.length <= 10) {
      return aggregatedChartData.length * 150;
    } else {
      return aggregatedChartData.length * (55);
    }
  }
}

Fudal avatar Jun 15 '23 12:06 Fudal

@imaNNeo I've added more information.

Fudal avatar Jun 19 '23 06:06 Fudal

In Flutter 3.10.5, the same thing happens

Fudal avatar Jun 28 '23 12:06 Fudal

I ran the app and this is what I see: (It seems working well)

https://github.com/imaNNeo/fl_chart/assets/7009300/31a8fcdc-e0ac-487c-832f-b268b0a3e31b

imaNNeo avatar Jul 31 '23 22:07 imaNNeo