Perché fl_chart
Visualizzare dati in modo chiaro è spesso il cuore di dashboard, app finanziarie e strumenti di monitoraggio. In Flutter la libreria di riferimento per questo scopo è fl_chart: leggera, altamente personalizzabile e costruita interamente su CustomPaint, il che garantisce animazioni fluide e rendering nativo su tutte le piattaforme.
In questa guida vedremo come creare grafici a linee, a barre e a torta, gestendo interazioni e animazioni.
Installazione
Aggiungi la dipendenza al tuo pubspec.yaml:
dependencies:
fl_chart: ^0.69.0
Poi esegui flutter pub get. Ricorda di controllare l'ultima versione disponibile su pub.dev, dato che l'API viene aggiornata frequentemente.
Grafico a linee
Il LineChart è ideale per mostrare andamenti nel tempo. La configurazione avviene tramite LineChartData:
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
class VenditeLineChart extends StatelessWidget {
const VenditeLineChart({super.key});
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 1.7,
child: LineChart(
LineChartData(
gridData: const FlGridData(show: true),
titlesData: const FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(showTitles: true, reservedSize: 40),
),
rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
),
borderData: FlBorderData(show: true),
lineBarsData: [
LineChartBarData(
spots: const [
FlSpot(0, 3),
FlSpot(1, 1),
FlSpot(2, 4),
FlSpot(3, 2),
FlSpot(4, 5),
],
isCurved: true,
color: Colors.blue,
barWidth: 3,
dotData: const FlDotData(show: true),
belowBarData: BarAreaData(
show: true,
color: Colors.blue.withOpacity(0.2),
),
),
],
),
),
);
}
}
Ogni punto è rappresentato da un FlSpot(x, y). Con isCurved: true la linea viene interpolata in modo smussato, mentre belowBarData riempie l'area sottostante con un gradiente o un colore.
Personalizzare le etichette degli assi
Un errore comune è lasciare etichette numeriche poco leggibili. Puoi mappare i valori a testi personalizzati con getTitlesWidget:
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) {
const giorni = ['Lun', 'Mar', 'Mer', 'Gio', 'Ven'];
final index = value.toInt();
if (index < 0 || index >= giorni.length) {
return const SizedBox.shrink();
}
return Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(giorni[index]),
);
},
),
),
Grafico a barre
Il BarChart usa BarChartGroupData per raggruppare le barre. Ecco un esempio con una barra per gruppo:
BarChart(
BarChartData(
alignment: BarChartAlignment.spaceAround,
maxY: 10,
barGroups: [
for (var i = 0; i < 5; i++)
BarChartGroupData(
x: i,
barRods: [
BarChartRodData(
toY: (i + 1) * 1.5,
color: Colors.teal,
width: 18,
borderRadius: BorderRadius.circular(4),
),
],
),
],
),
)
Grafico a torta
Il PieChart è perfetto per mostrare proporzioni:
PieChart(
PieChartData(
sectionsSpace: 2,
centerSpaceRadius: 40,
sections: [
PieChartSectionData(
value: 40,
color: Colors.blue,
title: '40%',
radius: 60,
),
PieChartSectionData(
value: 30,
color: Colors.orange,
title: '30%',
radius: 60,
),
PieChartSectionData(
value: 30,
color: Colors.green,
title: '30%',
radius: 60,
),
],
),
)
Con centerSpaceRadius maggiore di zero ottieni un grafico a ciambella (donut chart).
Gestire le interazioni
fl_chart supporta il tocco tramite LineTouchData, BarTouchData e PieTouchData. Ad esempio, per aggiornare lo stato al tap su una fetta:
PieChartData(
pieTouchData: PieTouchData(
touchCallback: (event, response) {
if (response?.touchedSection != null) {
final index = response!.touchedSection!.touchedSectionIndex;
// aggiorna lo stato, ad esempio evidenziando la sezione
}
},
),
sections: sections,
)
Combinando il callback con un StatefulWidget puoi evidenziare la sezione selezionata aumentando il radius o mostrando un tooltip personalizzato.
Animazioni
Molti grafici fl_chart animano automaticamente quando cambiano i dati. Puoi controllare durata e curva passando i parametri al costruttore:
LineChart(
data,
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
)
Best practice
- Incapsula la configurazione: crea metodi separati per
gridData,titlesDatae i dati, evitando widgetbuildtroppo lunghi. - Usa AspectRatio: i grafici hanno bisogno di vincoli di dimensione precisi;
AspectRatioo unSizedBoxevitano errori di layout. - Separa dati e presentazione: passa i modelli dal tuo state management (Riverpod, Bloc) e trasformali in
FlSpotoPieChartSectionDatain un layer dedicato. - Attenzione all'accessibilità: fl_chart disegna su canvas, quindi valuta di affiancare tabelle testuali o
Semanticsper gli screen reader.
Conclusione
fl_chart offre un ottimo equilibrio tra semplicità e potenza: partendo dai widget base puoi arrivare a dashboard complesse e interattive. Il segreto è costruire un layer che trasformi i tuoi dati di dominio nei modelli richiesti dalla libreria, mantenendo la UI pulita e testabile.
