FlutterFlowでパッケージを使う方法-Chartsのデザインをかっこよくしてみよう

FlutterFlowには基本的な機能が組み込まれていますが、複雑な処理や、デザインにはカスタマイズが必要です。その際にパッケージを使用するとアプリで実現したい機能の幅が広がります。そこで今回は、デザイン性の優れたパッケージを使ってチャートの作成方法を解説いたします。
FlutterFlowのカスタム機能
FlutterFlowには3つのカスタム機能があります。アクションを作成する「Custom Action」、簡易的な処理を作成する「Custom Function」、そして、Customのデザイン要素を作成する「Custom Widget」です。今回使用するのは、「Custom Widget」になります。
Custom Widget
今回は、以下のようなパイチャートを作成していきたいと思います。Custom Widgetにコードを書くことで、FluttreFlowにデフォルトでは備わっていないWidgetを作成できますが、今回はパッケージを利用しパイチャートを作成していきます。

パッケージとは
そもそもパッケージとはプログラムの部品集のようなもので、自分で全部書かなくても必要な機能をインポートして使えます。
実際、FlutterFlowには数十のパッケージが入っています。

Supabaseのデータ処理を行なうパッケージ、音声録音のパッケージ、http通信を行なうパッケージなど様々なパッケージがあることがわかります。
今回は、pie_chartを使用します。
パッケージを使う
パッケージを探す
Dart(Flutter)の場合、https://pub.dev/packagesからパッケージを見つけることができます。
今回はhttps://pub.dev/packages/pie_chartのパッケージを使用します。


必要情報
確認するポイント以下の2箇所になります。


自分でコードを書く場合はExampleも参考にしましょう。また、LLMを使用してコードを生成するケースではエラーが出てしまうことがあります。
その場合、古いバージョンのコードになっている可能性があるので、バーションを落として使用するか、最新バージョンで変更された部分を見つけ修正しましょう。
Custom Widgetを作成
パッケージを追加

では実際にCustomWidgetを追加していきます。先程のステップで取得した「pie_chart: ^5.4.0」を貼り付けます。
引数を設定
カスタムウィジェットを作成する際、外部から値を渡すための「引数」(パラメータ)を定義できます。これにより、ウィジェットの再利用性が高まります。端的に言えば、固定ではない変動するデータを入れるための設定です。

今回は配列のJSONからチャートを作成します。ラベル名になるname、実際の値、チャートのカラーです。このデータを引数dataにいれることを想定します。
Data Typeを「<List>JSON」で作成します。
[{"name": "住居費", "value": 35, "color": "#ff6347"},
{"name": "食費", "value": 25, "color": "#ffa500"},
{"name": "交通費", "value": 15, "color": "#4682b4"},
{"name": "娯楽費", "value": 10, "color": "#9932cc"},
{"name": "その他", "value": 15, "color": "#708090"}]
コードを生成
ではこの状態で右上の、「</>」ボタンをクリックし、下記にあるコードを貼り付けます。貼り付ける際はデフォルトで作成されているコード部分は削除します。

// Automatic FlutterFlow imports
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!
import 'package:pie_chart/pie_chart.dart';
class Charts extends StatefulWidget {
const Charts({
super.key,
this.width,
this.height,
required this.data,
});
final double? width;
final double? height;
final List<dynamic> data;
@override
State<Charts> createState() => _ChartsState();
}
class _ChartsState extends State<Charts> {
@override
Widget build(BuildContext context) {
// Convert the data from the input format to what pie_chart expects
Map<String, double> dataMap = {};
List<Color> colorList = [];
for (var item in widget.data) {
try {
String name = item['name'] ?? '';
double value = double.tryParse(item['value'].toString()) ?? 0;
String colorHex = item['color'] ?? '';
// Add to dataMap
dataMap[name] = value;
// Parse the color - handle both formats: with or without '#'
Color color = Color(0xFF000000); // Default color (black)
if (colorHex.isNotEmpty) {
if (colorHex.startsWith('#')) {
colorHex = colorHex.substring(1);
}
// Support both 6-digit and 8-digit hex
if (colorHex.length == 6) {
color = Color(int.parse('0xFF$colorHex'));
} else if (colorHex.length == 8) {
color = Color(int.parse('0x$colorHex'));
}
}
colorList.add(color);
} catch (e) {
print('Error parsing data item: $e');
}
}
// Return empty container if no data
if (dataMap.isEmpty) {
return Container(
width: widget.width ?? 300,
height: widget.height ?? 300,
child: Center(
child: Text(
'No data available',
style: TextStyle(color: Colors.grey),
),
),
);
}
return Container(
width: widget.width ?? 300,
height: widget.height ?? 300,
child: PieChart(
dataMap: dataMap,
chartType: ChartType.ring,
ringStrokeWidth: 40, // Adjust thickness of the ring
chartRadius: (widget.width ?? 300) / 2,
colorList: colorList,
legendOptions: LegendOptions(
showLegends: true,
legendPosition: LegendPosition.top,
showLegendsInRow: true,
legendTextStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
chartValuesOptions: ChartValuesOptions(
showChartValues: false, // Hide values inside the chart
),
centerText: "", // You can set a center text if needed
baseChartColor: Colors.grey.withOpacity(0.2),
animationDuration: Duration(milliseconds: 800),
),
);
}
}
App Stateを設定する
チャートのデータを保存するApp Stateを作成し、ダミーデータを追加しておきます。

「Add App State Variable」をクリックし、「data」、Data Typeを「<List>JSON」を選択します。
「data」をクリックするとTextFieldが表示されます。以下のデータを追加します。
[{"name": "住居費", "value": 35, "color": "#ff6347"},
{"name": "食費", "value": 25, "color": "#ffa500"},
{"name": "交通費", "value": 15, "color": "#4682b4"},
{"name": "娯楽費", "value": 10, "color": "#9932cc"},
{"name": "その他", "value": 15, "color": "#708090"}]
UIを追加する
ページデザイン画面に移動します。「Custom Widgets」セクションから作成したウィジェットをドラッグ&ドロップし追加します。

引数の設定
ウィジェットのプロパティパネルで引数の値を設定します。Custom Widgetは、width、hightが必須になります。今回は横幅、高さとも250pxに設定します。
引数dataの値は、先程のステップで作成したApp Stateを選択します。
AppStateから「data」を選択する。
これで完了です。テストモードで確認してみましょう。

さいごに
いかがだったでしょうか。パッケージを使用することで、複雑なアニメーションや、デザインを簡単に作成することができました。他にも様々なパッケージがありますので、ぜひ一度同様の手順で作成してみてください。
「アプリのアイディアはあるけど、実現する方法が分からない!」という方へ。
数々のアプリをFlutterFlowで開発してきた”FlutterFlow Cafe”運営会社が無料で相談に乗ります。
ーご相談はこちらから
・マッチングアプリ
・ライブEコマースアプリ
・生成AIを使ったサービス
などなど、アイディアをまずはお聞かせください。
▶︎こちらのリンクから質問に答えるだけでアプリ企画書が出来上がる資料もプレゼントしております。