Flutter GraphView is used to display data in graph structures. It can display Tree layout, Directed and Layered graph. Useful for Family Tree, Hierarchy View.

Overview

GraphView

Get it from pub package pub points popularity likes |

Flutter GraphView is used to display data in graph structures. It can display Tree layout, Directed and Layered graph. Useful for Family Tree, Hierarchy View.

alt Example alt Example alt Example

Overview

The library is designed to support different graph layouts and currently works excellent with small graphs.

You can have a look at the flutter web implementation here: http://graphview.surge.sh/

Layouts

Tree

Uses Walker's algorithm with Buchheim's runtime improvements (BuchheimWalkerAlgorithm class). Supports different orientations. All you have to do is using the BuchheimWalkerConfiguration.orientation with either ORIENTATION_LEFT_RIGHT, ORIENTATION_RIGHT_LEFT, ORIENTATION_TOP_BOTTOM and ORIENTATION_BOTTOM_TOP (default). Furthermore parameters like sibling-, level-, subtree separation can be set.

Useful for: Family Tree, Hierarchy View, Flutter Widget Tree,

Directed graph

Directed graph drawing by simulating attraction/repulsion forces. For this the algorithm by Fruchterman and Reingold (FruchtermanReingoldAlgorithm class) was implemented.

Useful for: Social network, Mind Map, Cluster, Graphs, Intercity Road Network,

Layered graph

Algorithm from Sugiyama et al. for drawing multilayer graphs, taking advantage of the hierarchical structure of the graph (SugiyamaAlgorithm class). You can also set the parameters for node and level separation using the SugiyamaConfiguration. Supports different orientations. All you have to do is using the SugiyamaConfiguration.orientation with either ORIENTATION_LEFT_RIGHT, ORIENTATION_RIGHT_LEFT, ORIENTATION_TOP_BOTTOM and ORIENTATION_BOTTOM_TOP (default).

Useful for: Hierarchical Graph which it can have weird edges/multiple paths

Usage

Currently GraphView must be used together with a Zoom Engine like InteractiveViewer. To change the zoom values just use the different attributes described in the InteractiveViewer class.

To create a graph, we need to instantiate the Graph class. Then we need to pass the layout and also optional the edge renderer.

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) => MaterialApp(
        home: TreeViewPage(),
      );
}

class TreeViewPage extends StatefulWidget {
  @override
  _TreeViewPageState createState() => _TreeViewPageState();
}

class _TreeViewPageState extends State<TreeViewPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      mainAxisSize: MainAxisSize.max,
      children: [
        Wrap(
          children: [
            Container(
              width: 100,
              child: TextFormField(
                initialValue: builder.siblingSeparation.toString(),
                decoration: InputDecoration(labelText: "Sibling Separation"),
                onChanged: (text) {
                  builder.siblingSeparation = int.tryParse(text) ?? 100;
                  this.setState(() {});
                },
              ),
            ),
            Container(
              width: 100,
              child: TextFormField(
                initialValue: builder.levelSeparation.toString(),
                decoration: InputDecoration(labelText: "Level Separation"),
                onChanged: (text) {
                  builder.levelSeparation = int.tryParse(text) ?? 100;
                  this.setState(() {});
                },
              ),
            ),
            Container(
              width: 100,
              child: TextFormField(
                initialValue: builder.subtreeSeparation.toString(),
                decoration: InputDecoration(labelText: "Subtree separation"),
                onChanged: (text) {
                  builder.subtreeSeparation = int.tryParse(text) ?? 100;
                  this.setState(() {});
                },
              ),
            ),
            Container(
              width: 100,
              child: TextFormField(
                initialValue: builder.orientation.toString(),
                decoration: InputDecoration(labelText: "Orientation"),
                onChanged: (text) {
                  builder.orientation = int.tryParse(text) ?? 100;
                  this.setState(() {});
                },
              ),
            ),
            RaisedButton(
              onPressed: () {
                final node12 = Node.Id(r.nextInt(100));
                var edge = graph.getNodeAtPosition(r.nextInt(graph.nodeCount()));
                print(edge);
                graph.addEdge(edge, node12);
                setState(() {});
              },
              child: Text("Add"),
            )
          ],
        ),
        Expanded(
          child: InteractiveViewer(
              constrained: false,
              boundaryMargin: EdgeInsets.all(100),
              minScale: 0.01,
              maxScale: 5.6,
              child: GraphView(
                graph: graph,
                algorithm: BuchheimWalkerAlgorithm(builder, TreeEdgeRenderer(builder)),
                paint: Paint()
                  ..color = Colors.green
                  ..strokeWidth = 1
                  ..style = PaintingStyle.stroke,
                builder: (Node node) {
                  // I can decide what widget should be shown here based on the id
                  var a = node.key.value as int;
                  return rectangleWidget(a);
                },
              )),
        ),
      ],
    ));
  }

  Random r = Random();

  Widget rectangleWidget(int a) {
    return InkWell(
      onTap: () {
        print('clicked');
      },
      child: Container(
          padding: EdgeInsets.all(16),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(4),
            boxShadow: [
              BoxShadow(color: Colors.blue[100], spreadRadius: 1),
            ],
          ),
          child: Text('Node ${a}')),
    );
  }

  final Graph graph = Graph()..isTree = true;
  BuchheimWalkerConfiguration builder = BuchheimWalkerConfiguration();

  @override
  void initState() {
    final node1 = Node.Id(1);
    final node2 = Node.Id(2);
    final node3 = Node.Id(3);
    final node4 = Node.Id(4);
    final node5 = Node.Id(5);
    final node6 = Node.Id(6);
    final node8 = Node.Id(7);
    final node7 = Node.Id(8);
    final node9 = Node.Id(9);
    final node10 = Node.Id(10);  
    final node11 = Node.Id(11);
    final node12 = Node.Id(12);

    graph.addEdge(node1, node2);
    graph.addEdge(node1, node3, paint: Paint()..color = Colors.red);
    graph.addEdge(node1, node4, paint: Paint()..color = Colors.blue);
    graph.addEdge(node2, node5);
    graph.addEdge(node2, node6);
    graph.addEdge(node6, node7, paint: Paint()..color = Colors.red);
    graph.addEdge(node6, node8, paint: Paint()..color = Colors.red);
    graph.addEdge(node4, node9);
    graph.addEdge(node4, node10, paint: Paint()..color = Colors.black);
    graph.addEdge(node4, node11, paint: Paint()..color = Colors.red);
    graph.addEdge(node11, node12);

    builder
      ..siblingSeparation = (100)
      ..levelSeparation = (150)
      ..subtreeSeparation = (150)
      ..orientation = (BuchheimWalkerConfiguration.ORIENTATION_TOP_BOTTOM);
  }
}

Using builder mechanism to build Nodes

You can use any widget inside the node:

Node node = Node.Id(fromNodeId) ;

builder: (Node node) {
                  // I can decide what widget should be shown here based on the id
                  var a = node.key.value as int;
                  if(a ==2)
                    return rectangleWidget(a);
                  else 
                    return circleWidget(a);
                },

Using Paint to color and line thickness

You can specify the edge color and thickness by using a custom paint

getGraphView() {
        return GraphView(
                graph: graph,
                algorithm: SugiyamaAlgorithm(builder),
                paint: Paint()..color = Colors.green..strokeWidth = 1..style = PaintingStyle.stroke,
              );
}

Color Edges individually

Add an additional parameter paint. Applicable for ArrowEdgeRenderer for now.

var a = Node();
var b = Node();
 graph.addEdge(a, b, paint: Paint()..color = Colors.red);

Add focused Node

You can focus on a specific node. This will allow scrolling to that node in the future, but for now , using it we can drag a node with realtime updates in force directed graph

 onPanUpdate: (details) {
        var x = details.globalPosition.dx;
        var y = details.globalPosition.dy;
        setState(() {
          builder.setFocusedNode(graph.getNodeAtPosition(i));
          graph.getNodeAtPosition(i).position = Offset(x,y);
        });
      },

Add drag nodes feature with animation

The code is there but not enabled yet due to dart null safety migration being more important

Extract info from any json to Graph Object

Now its a bit easy to use Ids to extract info from any json to Graph Object

For example, if the json is like this:

var json = {
   "nodes": [
     {"id": 1, "label": 'circle'},
     {"id": 2, "label": 'ellipse'},
     {"id": 3, "label": 'database'},
     {"id": 4, "label": 'box'},
     {"id": 5, "label": 'diamond'},
     {"id": 6, "label": 'dot'},
     {"id": 7, "label": 'square'},
     {"id": 8, "label": 'triangle'},
   ],
   "edges": [
     {"from": 1, "to": 2},
     {"from": 2, "to": 3},
     {"from": 2, "to": 4},
     {"from": 2, "to": 5},
     {"from": 5, "to": 6},
     {"from": 5, "to": 7},
     {"from": 6, "to": 8}
   ]
 };

Step 1, add the edges by using ids

  edges.forEach((element) {
      var fromNodeId = element['from'];
      var toNodeId = element['to'];
      graph.addEdge(Node.Id(fromNodeId), Node.Id(toNodeId));
    });

Step 2: Then using builder and find the nodeValues from the json using id and then set the value of that.

 builder: (Node node) {
                  // I can decide what widget should be shown here based on the id
                  var a = node.key.value as int;
                  var nodes = json['nodes'];
                  var nodeValue = nodes.firstWhere((element) => element['id'] == a);
                  return rectangleWidget(nodeValue['label'] as String);
                },

Using any widget inside the Node (Deprecated)

You can use any widget inside the node:

Node node = Node(getNodeText);

getNodeText() {
    return Container(
        padding: EdgeInsets.all(16),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(4),
          boxShadow: [
            BoxShadow(color: Colors.blue[100], spreadRadius: 1),
          ],
        ),
        child: Text("Node ${n++}"));
  }

Examples

Rooted Tree

alt Example

Rooted Tree (Bottom to Top)

alt Example

Rooted Tree (Left to Right)

alt Example

Rooted Tree (Right to Left)

alt Example

Directed Graph

alt Example alt Example

Layered Graph

alt Example

Inspirations

This library is basically a dart representation of the excellent Android Library GraphView by Team-Blox

I would like to thank them for open sourcing their code for which reason I was able to port their code to dart and use for flutter.

Future Works

  • Add nodeOnTap
  • Add Layered Graph
  • [] Use a builder pattern to draw items on demand.
  • [] Animations
  • [] Dynamic Node Position update for directed graph

License

MIT License

Copyright (c) 2020 Nabil Mosharraf

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Comments
  • Size Issue with SugiyamaAlgorithm

    Size Issue with SugiyamaAlgorithm

    There seems to be a positioning / size issue with the SugiyamaAlgorithm.

    The setup looks like:

    final _graph = Graph()..isTree = true
    
    GraphView(
                    graph: _graph,
                    algorithm: SugiyamaAlgorithm(SugiyamaConfiguration()
        ..nodeSeparation = 40
        ..levelSeparation = 50),
                    builder: (node) {
                    //_buildEdge returns a random value between 100 and 300 
                      return _buildEdge(payload!);
                    },
                  ),
    

    Check out the screenshot.

    Bildschirmfoto 2021-08-04 um 16 03 11

    Do you need any additional information from my side?

    opened by stefanschaller 19
  • How to center tree on the canvas ?

    How to center tree on the canvas ?

    I am using this plugin to display Family tree. And it does not center when displayed. Screenshot_20210119-202838

    I need to center horizontally like this on small tree and big family tree when first displayed : Screenshot_20210119-203319

    How to do it ?

    opened by olzii 8
  • Paint is not always complete

    Paint is not always complete

    I noticed with some graphs when you zoom you lose part of the painting:

    This is with graphview: ^0.6.5 Flutter (Channel beta, 1.24.0-10.2.pre, on Microsoft Windows [Version 10.0.19041.685], locale en-US)

    Screenshot (231)

    Screenshot (230)

    opened by jrheisler 8
  • Dart Migration w/o annotations

    Dart Migration w/o annotations

    https://github.com/nabil6391/graphview/issues/21

    Not tested, but passes analysis. I am using in my own project and will follow up with opinions.

    I used the Dart migration tools without any annotation coloring the results. Then made some patches here and there. You may want to go through it yourself as there is an opportunity to make the API a bit safer by shifting types to be non-nullable. Without annotations the migration tends to just make things explicitly null able.

    Also, probably a good idea to major version bump and add a -beta tag to the version if you feel this is still in beta.

    opened by MateusAmin 7
  • Feature request: Create graph based on data entries and provide builder argument

    Feature request: Create graph based on data entries and provide builder argument

    Hi, thanks for building and maintaining such a great package.

    I wonder if it would be possible to allow generating a graph based on purely data classes and not widgets.

    Here's what I mean. Now nodes need to be created with widgets as their arguments:

    final node = Node(
      MyWidget(
        data: data,
      ),
      key: Key(data.id),
    );
    graph.addNode(node);
    

    What I would love to see is to be able to just provide some data or id:

    final node = NodeData(
      id: data.id
    );
    graph.addNode(node);
    

    And then when creating a GraphView I would be able to provide builder:

    GraphView(
      graph: graph,
      algorithm: g.BuchheimWalkerAlgorithm(
        g.BuchheimWalkerConfiguration(),
        g.TreeEdgeRenderer(builder),
      builder: (data){
        // I can decide what widget should be shown here
        return MyWidget(data: data);
      }
    ),
    

    This would simplify populating graph data and would abstract Flutter/material dependencies

    enhancement 
    opened by orestesgaolin 6
  • how to let the graph scroll while has more nodes,but not zoom

    how to let the graph scroll while has more nodes,but not zoom

    i dont want to let the graph zoom small,but want to the graph can scrool left to right,or top to bottom while i have lots of nodes to show,how can i do it?

    opened by xiaobingcaicai 5
  • Not able to connect from 2 node to 1 node

    Not able to connect from 2 node to 1 node

    I tried to build a graph for family tree, requirement is from father and mother i need to conenct to child(2 node to 1) using BuchheimWalkerConfiguration algorith, but I'm not able to connect like that.

    opened by naaf-44 5
  • Graph so big nothing is visible unless zooming out, centering around `Layout.setFocusedNode` could be a fix

    Graph so big nothing is visible unless zooming out, centering around `Layout.setFocusedNode` could be a fix

    Made a video of how the graph looks: https://youtu.be/-oLNpC1voJs

    You can see that the top left corner of the graph view (where the graph view seems to always start) is empty, often with every nodes and edge off-screen.

    I had to zoom out alot to be able to start seeing some graph data. If we could "focus" on the focusedNode we'd guarantee that this wouldn't happen.

    Any other suggestions on making this work so it doesn't look to the user as though there is no graph?

    opened by claudiu-bele 5
  • Index out of range

    Index out of range

    I'm not sure if this is exactly related, but this is what happens. I am moving from 0.6.1 - 0.6.5, the orientation works fantastically, thank you. But there seems to be something going when changing out edges and nodes.

    I am driving this from a database. Data comes in, map to a list of objects that define the nodes and arrows.

    With 0.6.1 this works fine, as I am not sure what nodes I will be drawing each time, they all go away, along with the edges:

    graph.edges.clear(); graph.nodes.clear();

    I have also done this:

    List<gv.Edge> edges = [];
    graph.edges.forEach((element) {edges.add(element);});
    graph.removeEdges(edges);
    
    List<gv.Node> nodes = [];
    graph.nodes.forEach((element) {nodes.add(element);});
    graph.removeNodes(nodes);
    

    Both works great for 0.6.1

    But, 0.6.5 I get the attached error Screenshot (277)

    opened by jrheisler 5
  • Use BuchheimWalkerConfiguration to show tree merge node has problem

    Use BuchheimWalkerConfiguration to show tree merge node has problem

    I use BuchheimWalkerConfiguration like this, there are 2 branch and one merge node, it's OK

    `graph.addEdge(node1, node2, paint: Paint()..color = Colors.red); graph.addEdge(node2, node6); graph.addEdge(node6, node5);

    graph.addEdge(node2, node3); graph.addEdge(node3, node4); graph.addEdge(node4, node5);` image

    but if i change the order like this, it will show wrong connect line

    `graph.addEdge(node1, node2, paint: Paint()..color = Colors.red); graph.addEdge(node2, node3); graph.addEdge(node3, node4); graph.addEdge(node4, node5);

    graph.addEdge(node2, node6); graph.addEdge(node6, node5);` image

    opened by zhangxinagjunHJH 5
  • Handle disconnected nodes

    Handle disconnected nodes

    Is there a way to handle for nodes that aren't connected to the main branch? I guess I'm asking whether it is possible to show two disconnected networks in the same interactive viewer. Currently if not all nodes are connected they are drawn on top of each other.

    opened by roberteverman 5
  • Why In SugiyamaAlgorithm nodes are aligned with top when tree depth is unbalanced

    Why In SugiyamaAlgorithm nodes are aligned with top when tree depth is unbalanced

    0414DA52-D30A-4937-9CF3-A60DDB58DEB1_1_201_a

    Why Node 1 is not in the same level of node 2. But when i add 3 more on top of node 1 then it will comes on the same level of Node 2.

    Please help to figure this out...

    opened by lakharasachin-qf 3
  • How to scale and center a graph so that the whole graph is visible

    How to scale and center a graph so that the whole graph is visible

    Thank you for the great package!

    I am trying to show a graph and I want that it is centered and scaled to a size so that the whole graph is visible. Is this possible?

    This is what I have: drawing

    This is what I would like to have: drawing

    opened by CaptainDario 0
  • [Bug] TreeEdgeRenderer can't highlight paint to parent properly

    [Bug] TreeEdgeRenderer can't highlight paint to parent properly

    Using the sample from the README, and with algorithm: BuchheimWalkerAlgorithm(builder, TreeEdgeRenderer(builder)), I am trying to highlight the path from node to topmost parent. Because juncture points in a tree edge are associated with the last-drawn node, the full path can't be highlighted correctly, resulting in this situation:

    image

    opened by 0xNF 1
  • Nodes overlap in complex graphs

    Nodes overlap in complex graphs

    Bildschirmfoto 2022-08-03 um 10 29 54

    Hello, We use the plugin (graphview: ^1.1.1) with the Sugiyama algorithm. In more complex graphs, the individual nodes often overlap. As can be seen in the attached image, each branch is followed by a green and a red path. However, in the marked area, the red and green paths overlap.

    Do you know what could cause this problem and how to fix it?

    opened by lmis-frontend 4
  • Is it possible to position leaf nodes on the same level?

    Is it possible to position leaf nodes on the same level?

    Hello,

    I am using graphview to create an organization chart for my company. I am now wondering if it is possible to position all leaf nodes (in my case individual teams) at the same level, regardless of how long the chain of managers above the team is.

    I have considered (but not yet tested) using virtual nodes between the team and the manager to move the leaf node down X levels. Is there a better solution to my problem?

    I have created a diagram to illustrate my goal:

    Current: Screenshot 2022-07-21 at 10 55 51

    Target: Screenshot 2022-07-21 at 10 56 10

    opened by mway-niels 1
Owner
Nabil Mosharraf
Android Lead.Love to build best mobile experiences using Android, iOS and Flutter. I Know React, javasript, Python, Kotlin/java, Flutter using Dart
Nabil Mosharraf
A powerful 🚀 Android chart view / graph view library, supporting line- bar- pie- radar- bubble- and candlestick charts as well as scaling, panning and animations.

⚡ A powerful & easy to use chart library for Android ⚡ Charts is the iOS version of this library Table of Contents Quick Start Gradle Maven Documentat

Philipp Jahoda 36k Dec 28, 2022
This project is used to introduce the use of flutter canvas, include draw chart, clip image's path and draw progress indicator.

flutter_canvas This project is used to introduce the use of flutter canvas, include draw chart, clip image's path and draw progress indicator. draw ch

YouXianMing 9 Oct 27, 2022
Stores and manages the data of your week expenses with a chart

personal_expenses_app A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you st

null 1 Dec 26, 2021
A Flutter data visualization library based on Grammar of Graphics.

Graphic is now under a total refactoring. The prior available version code is here: v0.3.0 . A Flutter data visualization library based on Grammar of

LIN Chen 906 Jan 3, 2023
Tiny charts 🤏 - Sparkline charts for fast data visualization on Flutter apps

Tiny charts ?? - Sparkline charts for fast data visualization on Flutter apps

rows 15 Dec 10, 2022
In this project you will see how to generate charts with the data from the Firestore.

FlutterChartFirestore Flutter Tutorial - Flutter Charts+Firestore Video series can be watched here https://youtu.be/HGkbPrTSndM Getting Started In thi

Whatsupcoders 49 Oct 21, 2022
Animated radial and pie charts for Flutter

Flutter Circular Chart A library for creating animated circular chart widgets with Flutter, inspired by Zero to One with Flutter. Overview Create easi

Victor Choueiri 387 Dec 26, 2022
Elegant OHLC Candlestick and Trade Volume charts for @Flutter

flutter_candlesticks Elegant OHLC Candlestick and Trade Volume charts for Flutter Usage Install for Flutter with pub. Property Description data Requir

Trent Piercy 402 Dec 21, 2022
A powerful Flutter chart library, currently supporting Line Chart, Bar Chart, Pie Chart, Scatter Chart and Radar Chart.

FL Chart ?? A library to draw fantastic charts in Flutter ?? Chart Types LineChart BarChart PieChart Read More Read More Read More ScatterChart RadarC

Iman khoshabi 5.2k Dec 27, 2022
A beautiful bezier line chart widget for flutter that is highly interactive and configurable.

Bezier Chart A beautiful bezier line chart widget for flutter that is highly interactive and configurable. Features Multi bezier lines Allow numbers a

Aeyrium 428 Dec 21, 2022
[reborned barcode_scan] A flutter plugin for reading 2D barcodes and QR codes.

Reborned ?? Original barcode_scan was discontinued, so barcode_scan2 was borned with sound null safety support ?? barcode_scan2 A flutter plugin for s

Masayuki Ono (mono) 61 Jan 6, 2023
Maybe this is the best k chart in Flutter.Support drag,scale,long press,fling.And easy to use.

k_chart Maybe this is the best k chart in Flutter.Support drag,scale,long press,fling.And easy to use. display image gif Getting Started Install depen

OpenFlutter 342 Jan 9, 2023
Flutter chart library contains depth charts supporting various indicators and zooming

flutter_k_chart 介绍 一个仿火币的flutter图表库包含深度图,支持各种指标及放大缩小、平移等操作 webdemo演示 Demo v0.1.0:下载 APK 演示 简单用例 1.在 pubspec.yaml 中添加依赖 本项目数据来自火币openApi,火币的接口可能需要翻墙,接口

gwh 259 Dec 30, 2022
A simple candlestick chart for flutter. Supports smooth scroll and zoom

simple_candlestick_chart A simple candlestick chart for flutter. Supports smooth

7c00 14 Oct 17, 2022
:bar_chart: [wip] Create beautiful, responsive, animated charts using a simple and intuitive API.

fcharts A work-in-progress chart library for Flutter. Until version 1.0.0 the API is subject to change drastically. Needless to say, fcharts is not pr

Keenan Thompson 323 Dec 21, 2022
Draw dashed lines with any shape and style you want. Just like that.

dashed_line Draw dashed lines with any shape and style you want. Just like that. Usage Add the dependency to your pubspec.yaml (you can see the newest

LeanCode 16 Dec 20, 2022
Track your habits day by day and check your result like the GitHub's contributions board

Habits Diary Track your habits day by day and see your result like the GitHub's contributions board Download Support If you want to support this proje

Pigna 25 Oct 27, 2022
Charts Library for Flutter, written in Dart with Flutter.

Table of Contents New in the current release Illustration of the new "iterative auto layout" feature Autolayout step 1 Autolayout step 2 Autolayout st

Milan Zimmermann 225 Dec 25, 2022
Beautiful sparkline charts for Flutter

flutter_sparkline Beautiful sparkline charts for Flutter. Installation Install the latest version from pub. Quick Start Import the package, create a S

Victor Choueiri 255 Dec 21, 2022