DEV Community

Cover image for Creating Beautiful Charts in Flutter with fl_chart
Sanjay Adhikari
Sanjay Adhikari

Posted on

1

Creating Beautiful Charts in Flutter with fl_chart

๐Ÿ“Š A developer-friendly guide to visualizing data with ease in Flutter apps

Introduction

Data visualization is a powerful way to present complex information clearly and interactively. Whether you're building a fitness tracker, finance app, or analytics dashboard, charts can greatly enhance the user experience. In Flutter, the fl_chart package makes it easy to add beautiful and customizable charts to your apps.

In this blog, we'll explore how to use fl_chart to create different types of charts โ€” line, bar, pie, and radar โ€” and customize them to match your appโ€™s style.

1. Getting Started with fl_chart

To begin, add the fl_chart package to your pubspec.yaml file:

dependencies:
  fl_chart: ^0.70.2
Enter fullscreen mode Exit fullscreen mode

Then run:

flutter pub get
Enter fullscreen mode Exit fullscreen mode

Now import it into your Dart file:

import 'package:fl_chart/fl_chart.dart';
Enter fullscreen mode Exit fullscreen mode

2. Line Chart โ€“ Tracking Trends

A line chart is ideal for showing data over time, like daily temperature or stock prices.

LineChart(
  LineChartData(
    lineBarsData: [
      LineChartBarData(
        spots: [
          FlSpot(0, 3),
          FlSpot(1, 1),
          FlSpot(2, 4),
          FlSpot(3, 1.5),
        ],
        isCurved: true,
        colors: [Colors.blue],
        barWidth: 4,
        belowBarData: BarAreaData(show: true, colors: [Colors.blue.withOpacity(0.3)]),
      ),
    ],
  ),
)
Enter fullscreen mode Exit fullscreen mode

โœ… Tip: Use isCurved: true for a smooth line.

Line Chart Image

3. Bar Chart โ€“ Comparing Data

Bar charts are great for side-by-side comparisons, like monthly expenses or category-wise sales.

BarChart(
  BarChartData(
    barGroups: [
      BarChartGroupData(
        x: 0,
        barRods: [BarChartRodData(toY: 8, color: Colors.orange)],
      ),
      BarChartGroupData(
        x: 1,
        barRods: [BarChartRodData(toY: 10, color: Colors.orange)],
      ),
    ],
  ),
)
Enter fullscreen mode Exit fullscreen mode

โœ… Tip: Customize spacing and axis titles for better readability.

Bar Chart Image

4. Pie Chart โ€“ Proportional Insights

Pie charts work well for showing proportional data, such as time spent on different tasks or market shares.

PieChart(
  PieChartData(
    sections: [
      PieChartSectionData(value: 40, title: 'Work', color: Colors.green),
      PieChartSectionData(value: 30, title: 'Play', color: Colors.blue),
      PieChartSectionData(value: 30, title: 'Rest', color: Colors.purple),
    ],
  ),
)
Enter fullscreen mode Exit fullscreen mode

โœ… Tip: You can use titleStyle to stylize section labels.

Pie Chart Image

5. Radar Chart โ€“ Comparing Multiple Dimensions

Radar charts are perfect for showing multiple skills or features in a circular format.

RadarChart(
  RadarChartData(
    dataSets: [
      RadarDataSet(
        dataEntries: [
          RadarEntry(value: 5),
          RadarEntry(value: 4),
          RadarEntry(value: 3),
          RadarEntry(value: 4),
        ],
        borderColor: Colors.teal,
        fillColor: Colors.teal.withOpacity(0.3),
      ),
    ],
    radarBackgroundColor: Colors.transparent,
    titleTextStyle: TextStyle(color: Colors.black, fontSize: 14),
    getTitle: (index) {
      return ['Coding', 'Design', 'Debugging', 'Testing'][index];
    },
  ),
)
Enter fullscreen mode Exit fullscreen mode

โœ… Tip: Keep it minimal โ€” too many axes can clutter the chart.

Radar Chart Image

6. Real-Life Use Case: Fitness Dashboard

Imagine building a Fitness Dashboard where:

  • Line chart shows weekly calorie burn
  • Bar chart tracks daily steps
  • Pie chart represents activity breakdown
  • Radar chart compares fitness skills

This combination of charts provides an engaging, insightful UI.

7. Customization Tips

  • Use gradients for eye-catching charts
  • Show tooltips on tap using touchData
  • Use fl_chart with Bloc or Provider to show real-time data
  • Animate transitions for smoother user experience

8. Add Animations to the Chart

  • Add animation using AnimatedController and SingleTickerProviderStateMixin
  • Code for FadeIn and SlideIn animations are shown below
class FadeInLineChart extends StatefulWidget {
  const FadeInLineChart({super.key});

  @override
  State<FadeInLineChart> createState() => _FadeInLineChartState();
}

class _FadeInLineChartState extends State<FadeInLineChart>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _opacityAnimation;

  @override
  void initState() {
    super.initState();

    // Animation controller for fade effect
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 3),
    );

    // Opacity animation from 0 to 1
    _opacityAnimation = Tween<double>(begin: 0, end: 1).animate(
      CurvedAnimation(parent: _controller, curve: Curves.easeIn),
    );

    // Trigger animation
    Future.delayed(const Duration(milliseconds: 1000), () {
      _controller.forward(); // Start fade animation
    });
  }

  @override
  void dispose() {
    _controller.dispose(); // Clean up animation controller
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ClipRect(
      child: AnimatedContainer(
        duration: const Duration(seconds: 1),
        curve: Curves.easeOutExpo,
        height: 300,
        child: FadeTransition(
            opacity: _opacityAnimation,
            child: LineChart(
              LineChartData(
                lineBarsData: [
                  LineChartBarData(
                    spots: [
                      FlSpot(0, 1),
                      FlSpot(1, 3),
                      FlSpot(2, 2),
                      FlSpot(3, 4),
                      FlSpot(4, 3.5),
                      FlSpot(5, 4),
                    ],
                    isCurved: true,
                    color: Colors.blue,
                    barWidth: 4,
                    isStrokeCapRound: true,
                    belowBarData: BarAreaData(show: false),
                  ),
                ],
                titlesData: FlTitlesData(show: true),
                borderData: FlBorderData(show: true),
                minX: 0,
                maxX: 5,
                minY: 0,
                maxY: 5,
              ),
              duration: const Duration(milliseconds: 800),
              curve: Curves.easeInOut,
            )),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

FadeIn LineChart

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

  @override
  State<SlideInLineChart> createState() => _SlideInLineChartState();
}

class _SlideInLineChartState extends State<SlideInLineChart> {
  double _chartHeight = 0; // Initial height

  @override
  void initState() {
    super.initState();
    // Trigger animation after a short delay
    Future.delayed(const Duration(milliseconds: 300), () {
      setState(() {
        _chartHeight = 300; // Final chart height
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return ClipRect(
      child: AnimatedContainer(
        duration: const Duration(seconds: 2),
        curve: Curves.easeOutExpo,
        height: _chartHeight,
        child: _chartHeight > 0
            ? LineChart(
                LineChartData(
                  lineBarsData: [
                    LineChartBarData(
                      spots: [
                        FlSpot(0, 1),
                        FlSpot(1, 3),
                        FlSpot(2, 2),
                        FlSpot(3, 4),
                        FlSpot(4, 3.5),
                        FlSpot(5, 4),
                      ],
                      isCurved: true,
                      color: Colors.blue,
                      barWidth: 4,
                      isStrokeCapRound: true,
                      belowBarData: BarAreaData(show: false),
                    ),
                  ],
                  titlesData: FlTitlesData(show: true),
                  borderData: FlBorderData(show: true),
                  minX: 0,
                  maxX: 5,
                  minY: 0,
                  maxY: 5,
                ),
                duration: const Duration(milliseconds: 800),
                curve: Curves.easeInOut,
              )
            : const SizedBox.shrink(), // Prevent overflow when height is 0
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

SlideIn LineChart

  • Other animations

Smooth Bouncy Line Chart Animation

Smooth Bouncy Line Chart

Staggered Line Chart Animation

Staggered Line Chart

9. Wrapping Up

Using fl_chart in Flutter is straightforward and powerful. With just a few lines of code, you can add beautiful, interactive charts that elevate your appโ€™s UI and UX.

Start with the basics, explore the customization options, and before long, youโ€™ll be building dashboards that impress users and stakeholders alike.

โœ… Want to Try It Out?

  • Add fl_chart to your next Flutter project.
  • Share your custom charts on LinkedIn or GitHub.
  • Comment below if you want a full sample project!

Top comments (0)

๐Ÿ‘‹ Kindness is contagious

Explore this practical breakdown on DEVโ€™s open platform, where developers from every background come together to push boundaries. No matter your experience, your viewpoint enriches the conversation.

Dropping a simple โ€œthank youโ€ or question in the comments goes a long way in supporting authorsโ€”your feedback helps ideas evolve.

At DEV, shared discovery drives progress and builds lasting bonds. If this post resonated, a quick nod of appreciation can make all the difference.

Okay