Help us understand the problem. What is going on with this article?

Flutter charts_flutterの使い方

charts_flutterの使い方

Flutter のパッケージであるcharts_flutterの使い方の忘却録
※※※ 20201014追記 ※※※
このコードを書いている時のcloud_firestoreは0.13.6であるが、
現在の最新は0.14.1+3のため、データの取得方法が異なるので、注意
※※※※※※※※※※※※※※※※※※※

開発環境

PC:macOS Catalina
エディター:Visual Studio Code
charts_flutter:0.9.0(2020/8/2現在の最新バージョン)

製作物

下記画像のようなチャートを作成
Simulator Screen Shot - iPhone 11 - 2020-08-02 at 14.30.36.png

コード

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^0.4.5
  firebase_auth: ^0.16.1
  cloud_firestore: ^0.13.6
       
       
       
  charts_flutter: ^0.9.0  <- 追加

chart.dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:charts_flutter/flutter.dart' as charts;

class BudgetPage extends StatefulWidget {
  BudgetPage({Key key}) : super(key: key);
  @override
  _BudgetPageState createState() => _BudgetPageState();
}

class _BudgetPageState extends State<BudgetPage> {
  final String _collectionName = "users";
  List _productsDataList;
  int _itemCount = 0;
  int _profit = 0;
  int _cost = 0;
  List _profitArray ;
  List _costArray;
  bool _getProfitDataFlg = false;
  List<charts.Series<BudgetChart, String>> _series = [];
  List _pieChartArray = [];

  void _getProfitData() async {
    final QuerySnapshot allcollections = await Firestore.instance.collection(this._collectionName).getDocuments();
    final FirebaseUser user = await FirebaseAuth.instance.currentUser();
    final String userID = user.uid;

    for (int i = 0; i < allcollections.documents.length; i++) {
      Map<String, dynamic> currentUserData = allcollections.documents[i].data;

      if (currentUserData["uid"] == userID) {
        currentUserData.forEach((key, value) {
          if (key == "products") {
            this._productsDataList = value;
            this._itemCount = this._productsDataList.length;
          }
        });
      }
    }

    this._profitArray = List.filled(this._itemCount + 1, 0);
    this._costArray = List.filled(this._itemCount + 1, 0);
    this._pieChartArray = List.generate(this._itemCount + 1, (i)=>null);

    for (int i = 0; i < this._itemCount; i++) {
      List workingData = this._productsDataList[i]["working_data"];
      for (int j = 0; j < workingData.length; j++) {
        this._profit += (workingData[j]["shipment"] * workingData[j]["count"]);
        this._cost += workingData[j]["cost"];
      }

      this._profitArray[i + 1] = this._profit;
      this._costArray[i + 1] = this._cost;

      this._profit = 0;
      this._cost = 0;
    }

    for (int i = 0; i <= this._itemCount; i++) {
      for (int j = 0; j < this._itemCount; j++) {
        this._profitArray[0] += this._profitArray[j + 1];
        this._costArray[0] += this._costArray[j + 1];
      }
      _createChartData(i);
    }
  }

  // チャートデータを作成するメソッド
  void _createChartData(int index) {
    this._series = [
      charts.Series<BudgetChart, String>(
        id: 'BudgetChart',
        domainFn: (BudgetChart record, _) => record.word,
        measureFn: (BudgetChart record, _) => record.money,
        colorFn: (BudgetChart record, _) => record.color,
        data: [
           // BudgetChartのインスタンスを生成
           // 表示する文字、金額、色を指定する
          BudgetChart("収入", _profitArray[index], charts.MaterialPalette.green.shadeDefault),
          BudgetChart("支出", _costArray[index], charts.MaterialPalette.red.shadeDefault),
        ],
     // チャートに表示するラベル
        labelAccessorFn: (BudgetChart row, _) => '${row.word}: ${row.money}',
      ),
    ];
    this._pieChartArray[index] = this._series;

    setState(() {
      _getProfitDataFlg = true;
    });
  }

  // チャートのタイトルを表示するウィジェット
  Widget _titleArea(int index) {

    String titleText;

    if(index == 0){
      titleText = "合計収支";
    } else {
      titleText = this._productsDataList[index - 1]["product"];
    }

    return Container(
      margin: EdgeInsets.all(16.0),
      child: Center(
        child: Text(titleText),
      ),
    );
  }

  // Expandedを使用してチャートサイズを調整して表示するウィジェット
  Widget _showPieChart(int index) {
    return Container(
      child: Expanded(
        child: Container(
          margin: const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 16.0),
          child: charts.PieChart(this._pieChartArray[index],
            defaultRenderer: charts.ArcRendererConfig(
              arcRendererDecorators: [charts.ArcLabelDecorator()])),
        ),
      ),
    );
  }

  // "<", ">" アイコン表示するウィジェット
  Widget _showIcon(IconData icon, String label, int index) {
    Color color = Theme.of(context).primaryColorDark;

    // 先端と終端のアイコンを非表示
    if (index == 0){
      color = Colors.white70;
    } else if (index == this._itemCount + 1) {
      color = Colors.white70;
    }
    return Icon(icon, color: color);
  }

  _BudgetPageState() {
    _getProfitData();
  }

  @override
  Widget build(BuildContext context) {
    if (!_getProfitDataFlg) {
      return Center(
        child: CircularProgressIndicator(
          valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
        )
      );
    }

    final Size DEVICE_SIZE = MediaQuery.of(context).size;

    return Scaffold(
      appBar: AppBar(
        title: Text("収支記録"),
        backgroundColor: Colors.green[400],
      ),
      body: Container(
        child: PageView(
          scrollDirection: Axis.horizontal,
          // 各タブの内容
          children: [
            for (int i = 0; i <= this._itemCount; i++)
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  _showIcon(Icons.arrow_back_ios, "arrow_back_ios", i),
                  Card(
                    child: Container(
                      width: DEVICE_SIZE.width * 0.8,
                      height: DEVICE_SIZE.height * 0.7,
                      child: Column(
                        children: <Widget>[
                          _titleArea(i),
                          _showPieChart(i),
                        ],
                      ),
                    ),
                  ),
                  _showIcon(Icons.arrow_forward_ios, "arrow_forward_ios", i + 1), 
                ]
              ),
          ],
        ),
      )
    );
  }
}

// チャートクラス
class BudgetChart {
  final String word;
  final int money;
  final charts.Color color;

  BudgetChart(this.word, this.money, this.color);
}


参考

https://pub.dev/packages/charts_flutter

https://google.github.io/charts/flutter/gallery.html

mkurom
仕事ではC#を、たまーにC++でコードを書いています 最近はpython, PHP,flutterを勉強中 主に忘却録として書く予定。。。 エンジニア2年目
https://kobe-english-salon.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away