Disegnare grafici a barre e a linee in Flutter con fl_chart
GuideIntermedio35 min Flutter 3.x

Disegnare grafici a barre e a linee in Flutter con fl_chart

Visualizzare dati con fl_chart

La visualizzazione dei dati è una parte fondamentale di molte applicazioni: dashboard finanziarie, app per il fitness, statistiche di vendita e molto altro. In Flutter, uno dei pacchetti più potenti e flessibili per creare grafici è fl_chart.

In questo tutorial vedremo come integrare fl_chart in un progetto Flutter e costruire due tipi di grafici molto comuni: un grafico a barre (BarChart) e un grafico a linee (LineChart). Personalizzeremo gli assi, i colori, i tooltip interattivi e l'aspetto generale.

Al termine avrai una schermata con due grafici funzionanti e i fondamenti per crearne di più complessi.

  1. 1

    Aggiungere la dipendenza fl_chart

    Per prima cosa aggiungiamo il pacchetto fl_chart al progetto. Apri il file pubspec.yaml e aggiungi la dipendenza nella sezione dependencies, poi esegui flutter pub get dal terminale (o lascia che l'IDE lo faccia automaticamente).

    Verifica sempre l'ultima versione disponibile su pub.dev.

    dependencies:
      flutter:
        sdk: flutter
      fl_chart: ^0.69.0

    Risultato atteso

    Il pacchetto fl_chart viene scaricato e reso disponibile nel progetto senza errori.

  2. 2

    Preparare il modello dei dati

    Definiamo una semplice struttura dati che useremo per entrambi i grafici. Immaginiamo di voler rappresentare le vendite mensili. Creiamo una classe MonthlySales e una lista di esempio.

    In un'app reale questi dati arriverebbero da un'API o da un database, ma per il tutorial usiamo valori statici.

    class MonthlySales {
      final String month;
      final double amount;
    
      const MonthlySales(this.month, this.amount);
    }
    
    const salesData = <MonthlySales>[
      MonthlySales('Gen', 320),
      MonthlySales('Feb', 280),
      MonthlySales('Mar', 450),
      MonthlySales('Apr', 390),
      MonthlySales('Mag', 520),
      MonthlySales('Giu', 610),
    ];

    Risultato atteso

    Hai una lista tipizzata di dati pronta per essere visualizzata nei grafici.

  3. 3

    Creare un grafico a barre (BarChart)

    Costruiamo ora un widget che mostra i dati come grafico a barre. Mappiamo ogni elemento della lista in un BarChartGroupData, dove l'indice rappresenta la posizione sull'asse X e il valore l'altezza della barra.

    Usiamo BarChartRodData per definire l'aspetto di ogni barra (colore, larghezza, angoli arrotondati).

    import 'package:fl_chart/fl_chart.dart';
    import 'package:flutter/material.dart';
    
    class SalesBarChart extends StatelessWidget {
      const SalesBarChart({super.key});
    
      @override
      Widget build(BuildContext context) {
        return AspectRatio(
          aspectRatio: 1.6,
          child: BarChart(
            BarChartData(
              maxY: 700,
              barGroups: List.generate(salesData.length, (i) {
                return BarChartGroupData(
                  x: i,
                  barRods: [
                    BarChartRodData(
                      toY: salesData[i].amount,
                      color: Colors.blue,
                      width: 18,
                      borderRadius: const BorderRadius.vertical(
                        top: Radius.circular(6),
                      ),
                    ),
                  ],
                );
              }),
            ),
          ),
        );
      }
    }

    Risultato atteso

    Viene mostrato un grafico a barre con sei colonne blu di altezze diverse.

  4. 4

    Personalizzare gli assi e le etichette

    Per rendere il grafico leggibile aggiungiamo le etichette dei mesi sull'asse X e i valori sull'asse Y. Configuriamo titlesData con dei SideTitles personalizzati.

    Usiamo getTitlesWidget per restituire un widget testuale in base all'indice, recuperando il nome del mese dalla lista dei dati.

    BarChartData(
      maxY: 700,
      gridData: const FlGridData(show: true, drawVerticalLine: false),
      borderData: FlBorderData(show: false),
      titlesData: FlTitlesData(
        topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
        rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
        leftTitles: const AxisTitles(
          sideTitles: SideTitles(showTitles: true, reservedSize: 40, interval: 200),
        ),
        bottomTitles: AxisTitles(
          sideTitles: SideTitles(
            showTitles: true,
            getTitlesWidget: (value, meta) {
              final index = value.toInt();
              if (index < 0 || index >= salesData.length) {
                return const SizedBox.shrink();
              }
              return Padding(
                padding: const EdgeInsets.only(top: 6),
                child: Text(salesData[index].month),
              );
            },
          ),
        ),
      ),
      barGroups: /* come prima */ [],
    )

    Risultato atteso

    Il grafico mostra i nomi dei mesi sotto le barre e i valori numerici sull'asse verticale, con una griglia orizzontale di riferimento.

  5. 5

    Aggiungere un grafico a linee (LineChart)

    Ora rappresentiamo gli stessi dati come grafico a linee. Il cuore è il LineChartBarData, che riceve una lista di FlSpot (coppie x, y).

    Aggiungiamo un riempimento sotto la linea con belowBarData e attiviamo la curvatura con isCurved per un effetto più morbido.

    class SalesLineChart extends StatelessWidget {
      const SalesLineChart({super.key});
    
      @override
      Widget build(BuildContext context) {
        return AspectRatio(
          aspectRatio: 1.6,
          child: LineChart(
            LineChartData(
              minY: 0,
              maxY: 700,
              lineBarsData: [
                LineChartBarData(
                  isCurved: true,
                  color: Colors.deepPurple,
                  barWidth: 3,
                  dotData: const FlDotData(show: true),
                  belowBarData: BarAreaData(
                    show: true,
                    color: Colors.deepPurple.withOpacity(0.15),
                  ),
                  spots: List.generate(
                    salesData.length,
                    (i) => FlSpot(i.toDouble(), salesData[i].amount),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }

    Risultato atteso

    Appare una linea curva viola che collega i punti dei dati, con un'area sfumata sottostante.

  6. 6

    Abilitare i tooltip interattivi

    Per migliorare l'esperienza utente, aggiungiamo tooltip che mostrano il valore quando si tocca o si passa sopra un punto del grafico. Configuriamo la proprietà lineTouchData (o barTouchData per il grafico a barre).

    Personalizziamo il colore di sfondo del tooltip e il testo mostrato.

    LineChartData(
      minY: 0,
      maxY: 700,
      lineTouchData: LineTouchData(
        touchTooltipData: LineTouchTooltipData(
          getTooltipColor: (_) => Colors.black87,
          getTooltipItems: (touchedSpots) {
            return touchedSpots.map((spot) {
              final month = salesData[spot.x.toInt()].month;
              return LineTooltipItem(
                '$month\n€ ${spot.y.toStringAsFixed(0)}',
                const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
              );
            }).toList();
          },
        ),
      ),
      lineBarsData: [ /* come prima */ ],
    )

    Risultato atteso

    Toccando un punto della linea compare un tooltip con il nome del mese e il relativo importo.

  7. 7

    Comporre la schermata finale

    Infine assembliamo i due grafici in un'unica schermata, alternandoli con dei titoli. Usiamo una Column dentro un SingleChildScrollView per gestire schermi piccoli e aggiungiamo del padding.

    Questo è il punto di partenza per una dashboard completa: puoi collegare i dati a uno stato dinamico (Provider, Riverpod, ecc.) per aggiornare i grafici in tempo reale.

    class ChartsPage extends StatelessWidget {
      const ChartsPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Statistiche vendite')),
          body: SingleChildScrollView(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: const [
                Text('Vendite mensili (barre)',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                SizedBox(height: 16),
                SalesBarChart(),
                SizedBox(height: 32),
                Text('Andamento vendite (linea)',
                    style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                SizedBox(height: 16),
                SalesLineChart(),
              ],
            ),
          ),
        );
      }
    }

    Risultato atteso

    Una schermata scorrevole mostra il grafico a barre e quello a linee con i rispettivi titoli, entrambi funzionanti e interattivi.

CondividiXLinkedInFacebookWhatsApp

Commenti (0)

Ancora nessun commento. Inizia tu!