From 7bf59a486a6e93714294f3e9f69e548bbb6da97d Mon Sep 17 00:00:00 2001 From: Riccardo Cucia Date: Mon, 3 May 2021 09:05:35 +0200 Subject: [PATCH] Add Null-Safety support & Fix documentation. --- CHANGELOG.md | 5 + README.md | 2 +- example/README.md | 91 +++++++- example/lib/main.dart | 2 +- example/pubspec.lock | 11 +- example/pubspec.yaml | 66 +----- example/test/widget_test.dart | 32 --- lib/flutter_bargraph.dart | 388 +------------------------------- lib/src/bargraph.dart | 381 +++++++++++++++++++++++++++++++ pubspec.lock | 2 +- pubspec.yaml | 39 +--- test/flutter_bargraph_test.dart | 15 -- 12 files changed, 480 insertions(+), 554 deletions(-) delete mode 100644 example/test/widget_test.dart create mode 100644 lib/src/bargraph.dart delete mode 100644 test/flutter_bargraph_test.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 782d28c..d1ca4f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [1.1.0] - 2021-05-03 + +* Add Null-Safety support. +* Fix documentation. + ## [1.0.0] - 2021-04-11 * First release. diff --git a/README.md b/README.md index 17f714d..fb32eb5 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Add the following line to `pubspec.yaml`: ```yaml dependencies: - flutter_bargraph: ^1.0.0 + flutter_bargraph: ^1.1.0 ``` ### Basic setup diff --git a/example/README.md b/example/README.md index 4f2c5cc..fb32eb5 100644 --- a/example/README.md +++ b/example/README.md @@ -1,16 +1,87 @@ -# flutter_bargraph_example +# flutter_bargraph -Flutter simple example, single value bar graph viewer with indicators +[![Pub Package](https://img.shields.io/pub/v/flutter_bargraph.svg?style=flat-square)](https://pub.dartlang.org/packages/flutter_bargraph) [![Package Issue](https://img.shields.io/github/issues/rickypid/flutter_bargraph)](https://github.com/rickypid/flutter_bargraph/issues) +![Package License](https://img.shields.io/github/license/rickypid/flutter_bargraph) + +Bar Graph Indicator for Flutter. It graphically displays the current value on a bar graph and manages its animation when the value changes. you can customize the orientation and direction of the bar. + +| ![Image](https://github.com/rickypid/flutter_bargraph/blob/7f5bde4ebc40899079800127c815e01beac3abcb/doc/.media/example.gif?raw=true) | +| :------------: | +| **BarGraph** | + +## Features + +* Min/Max property +* Customizable colors and text style +* Vertical orientation, left to right and right to left direction +* Horizontal orientation, top to bottom and bottom to top direction +* Number of divisions customizable + +## Usage + +Make sure to check out [examples](https://github.com/rickypid/flutter_bargraph/tree/master/example). + +### Installation + +Add the following line to `pubspec.yaml`: + +```yaml +dependencies: + flutter_bargraph: ^1.1.0 +``` + +### Basic setup + +*The complete example is available [here](https://github.com/rickypid/flutter_bargraph/blob/master/example/lib/main.dart).* + +**BarGraph** requires you to provide `min`, `max` and `value`: +* `min` is the min value of BarGraph scale. +* `max` is the max value of BarGraph scale. +* `value` is the currently value of BarGraph scale. + +```dart +BarGraph( + min: 0, + max: 100.0, + value: 65.0, +); +``` + +### Advanced options + +#### Style + +* `orientation` is the scale orientation, default vertical from bottom. +* `indicatorStyle` is the scale indicators style, default BOTH, left and right visible. +* `indicatorSpacing` is the scale indicators spacing, default SPACE_AROUND, alternative SPACE_BETWEEN. + +#### Colors + +* `backgroundColor` is the background color og BarGraph. +* `barColor` is the color of actual value bar. +* `indicatorsColor` is the color of indicators scale. + +#### Indicators text + +* `textStyle` is the TextStyle of indicators text. +* `textAlign` is the Alignment of indicators text. +* `fractionDigits` is the number of fraction digits visible. +* `divisions` is the number of divisions of scale. +* `textFlex` is the percentage of portion used for text, remaining space is used for indicators. + + +#### Animation + +* `animationDuration` in milliseconds, it's duration time of animation when actual value changed. + + +### Example + +| ![Image](https://github.com/rickypid/flutter_bargraph/blob/master/doc/.media/example_space_around.png?raw=true) | ![Image](https://github.com/rickypid/flutter_bargraph/blob/master/doc/.media/example_space_around_horizontal.png?raw=true) | ![Image](https://github.com/rickypid/flutter_bargraph/blob/master/doc/.media/example_space_between.png?raw=true) | +| :------------: | :------------: | :------------: | +| **Vertical space around** | **Horizontal space around** | **Vertical space between** | -## Getting Started -This project is a starting point for a Flutter application. -A few resources to get you started if this is your first Flutter project: -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/example/lib/main.dart b/example/lib/main.dart index 548fa01..788008c 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -20,7 +20,7 @@ class MyApp extends StatelessWidget { } class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); + MyHomePage({Key? key, this.title = ''}) : super(key: key); final String title; @override diff --git a/example/pubspec.lock b/example/pubspec.lock index e9c817a..5782455 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -43,13 +43,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.15.0" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" fake_async: dependency: transitive description: @@ -63,7 +56,7 @@ packages: source: sdk version: "0.0.0" flutter_bargraph: - dependency: "direct main" + dependency: "direct dev" description: path: ".." relative: true @@ -157,5 +150,5 @@ packages: source: hosted version: "2.1.0" sdks: - dart: ">=2.12.0-0.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" flutter: ">=1.17.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 62cc10b..0cc359e 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,77 +1,19 @@ name: flutter_bargraph_example description: Flutter simple example, single value bar graph viewer with indicators - -# The following line prevents the package from being accidentally published to -# pub.dev using `pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 +version: 1.1.0 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: flutter: sdk: flutter - flutter_bargraph: - path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 dev_dependencies: flutter_test: sdk: flutter + flutter_bargraph: + path: ../ -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart deleted file mode 100644 index 9ca1523..0000000 --- a/example/test/widget_test.dart +++ /dev/null @@ -1,32 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import '../lib/main.dart'; - - - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/lib/flutter_bargraph.dart b/lib/flutter_bargraph.dart index f4d013f..4170682 100644 --- a/lib/flutter_bargraph.dart +++ b/lib/flutter_bargraph.dart @@ -1,388 +1,4 @@ +/// Adds `ScrollShadow` widget to add shadows to a scrollable child. Supports ScrollController and vertical or horizontal orientation. library flutter_bargraph; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -/// [BarGraphOrientation] Enum -enum BarGraphOrientation { - /// Bar orientation Vertical top to bottom - VERTICAL_FROM_TOP, - - /// Bar orientation Vertical bottom to top - VERTICAL_FROM_BOTTOM, - - /// Bar orientation Horizontal left to right - HORIZONTAL_FROM_LEFT, - - /// Bar orientation Horizontal right to left - HORIZONTAL_FROM_RIGHT, -} - -/// [BarGraphIndicatorStyle] Enum -enum BarGraphIndicatorStyle { - /// View all indicator - BOTH, - - /// View only left/Top indicator - ONLY_LEFT_OR_TOP, - - /// View only Right/Bottom indicator - ONLY_RIGHT_OR_BOTTOM, - - /// Hidden all indicator - NOTHING -} - -/// [BarGraphIndicatorSpacing] Enum -enum BarGraphIndicatorSpacing { - /// Is indicator spacing type - SPACE_AROUND, - - /// Is indicator spacing type - SPACE_BETWEEN, -} - -class BarGraph extends StatefulWidget { - /// Is [backgroundColor] of BarGraph - /// - /// Default Theme.of(context).scaffoldBackgroundColor - final Color backgroundColor; - - /// [barColor] is a color of BarGraph bar - /// - /// DefaultTheme.of(context).primaryColor - final Color barColor; - - /// [indicatorsColor] is a color of BarGraph line indicator - /// - /// Default: Theme.of(context).buttonColor - final Color indicatorsColor; - - /// [textStyle] is a TextStyle of BarGraph text label indicator - /// - /// Default: Text Widget default TextStyle - final TextStyle textStyle; - - /// [textAlign] is a Alignment of BarGraph text label indicator - /// - /// Default: Alignment.center - final Alignment textAlign; - - /// [value] is actual value of BarGraph bar - /// - /// Default: 15 - final double value; - - /// [min] is min value of BarGraph scale - /// - /// Default: 0 - final double min; - - /// [max] is max value of BarGraph scale - /// - ///Default: 100 - final double max; - - /// [divisions] is count of BarGraph indicators - /// - /// Default: 10 - final int divisions; - - /// [fractionDigits] is number of digits of BarGraph text label indicator - /// - /// Default: 2 - final int fractionDigits; - - /// [animationDuration] is a millisecond of animation duration on changed value of BarGraph - /// - /// Default: 200 milliseconds - final int animationDuration; - - /// [textFlex] is the percentage of portion used for text, remaining space is used for indicators. - /// - ///Default: 20% - final int textFlex; - - /// [orientation] is a orientation of BarGraph - /// - /// Default: BarGraphOrientation.VERTICAL_FROM_BOTTOM - /// - /// Possible orientation: - /// * BarGraphOrientation.VERTICAL_FROM_TOP - /// * BarGraphOrientation.VERTICAL_FROM_BOTTOM - /// * BarGraphOrientation.HORIZONTAL_FROM_LEFT - /// * BarGraphOrientation.HORIZONTAL_FROM_RIGHT - final BarGraphOrientation orientation; - - /// [indicatorStyle] is the scale indicators style - /// - /// Default: BarGraphIndicatorStyle.BOTH, left and right visible. - /// - /// Possible orientation: - /// * BarGraphIndicatorStyle.BOTH - /// * BarGraphIndicatorStyle.ONLY_LEFT_OR_TOP - /// * BarGraphIndicatorStyle.ONLY_RIGHT_OR_BOTTOM - /// * BarGraphIndicatorStyle.NOTHING - final BarGraphIndicatorStyle indicatorStyle; - - /// [indicatorSpacing] is the scale indicators spacing - /// - /// Default: BarGraphIndicatorSpacing.SPACE_AROUND - /// - /// Possible orientation: - /// * BarGraphIndicatorSpacing.SPACE_AROUND - /// * BarGraphIndicatorSpacing.SPACE_BETWEEN - final BarGraphIndicatorSpacing indicatorSpacing; - - /// Creates an [BarGraph] - /// Material design's - BarGraph( - {Key key, - this.backgroundColor, - this.barColor, - this.indicatorsColor, - this.textStyle, - this.textAlign = Alignment.center, - this.fractionDigits = 2, - this.value = 15, - this.divisions = 10, - this.min = 0, - this.max = 100, - this.animationDuration = 200, - this.orientation = BarGraphOrientation.VERTICAL_FROM_BOTTOM, - this.textFlex = 20, - this.indicatorStyle = BarGraphIndicatorStyle.BOTH, - this.indicatorSpacing = BarGraphIndicatorSpacing.SPACE_AROUND}) - : assert( - value >= min, 'The value is less than the specified minimum value'), - assert(value <= max, - 'The value is greater than the specified maximum value'), - assert(divisions > 0, 'Divisions must be greater than 0'), - assert(textFlex > 0 && textFlex < 100), - super(key: key); - - @override - _BarGraphState createState() => _BarGraphState(); -} - -enum _SideEnum { LEFT, RIGHT } - -class _BarGraphState extends State with TickerProviderStateMixin { - Animation _animation; - Tween _tween; - AnimationController _animationController; - double _valueImg; - - _BarGraphState(); - - @override - void initState() { - super.initState(); - _valueImg = widget.value; - _animationController = AnimationController( - duration: Duration(milliseconds: widget.animationDuration), - vsync: this); - _tween = Tween(begin: widget.min, end: widget.value); - _animation = _tween.animate(_animationController) - ..addListener(() { - setState(() {}); - }); - _animationController.forward(); - } - - void _updateValue() { - if (_valueImg != widget.value) { - _tween.begin = _animation.value; - _animationController.reset(); - _tween.end = widget.value; - _animationController.forward(); - _valueImg = widget.value; - } - } - - double _actualProgress() { - double progress = - (_animation.value - widget.min) / (widget.max - widget.min); - double offset = 0; - if (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND) - offset = ((1 / (widget.divisions + 1)) / 2); - return offset + (progress * (1 - (offset * 2))); - } - - Widget _getVerticalHorizontalPrincipalWidget(List children) { - if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_LEFT || - widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) - return Column( - children: children, - ); - else - return Row( - children: children, - ); - } - - Widget _getVerticalHorizontalSubWidget(List children) { - if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_LEFT || - widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) - return Row( - children: children, - mainAxisAlignment: - (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND) - ? MainAxisAlignment.spaceAround - : MainAxisAlignment.spaceBetween, - ); - else - return Column( - children: children, - mainAxisAlignment: - (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND) - ? MainAxisAlignment.spaceAround - : MainAxisAlignment.spaceBetween, - ); - } - - Widget _getVerticalHorizontalTextWidget(List children) { - if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_LEFT || - widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) - return Row( - children: children, - mainAxisAlignment: MainAxisAlignment.spaceAround, - ); - else - return Column( - children: children, - mainAxisAlignment: MainAxisAlignment.spaceAround, - ); - } - - List _getLabels() { - List widgets = List.generate(widget.divisions + 1, (index) { - Widget text; - if (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND || - (index > 0 && index < widget.divisions)) - text = Text( - (widget.min + - (index * ((widget.max - widget.min) / widget.divisions))) - .toStringAsFixed(widget.fractionDigits), - style: widget.textStyle); - else - text = null; - - return Expanded( - flex: (widget.indicatorSpacing == - BarGraphIndicatorSpacing.SPACE_AROUND || - (index > 0 && index < widget.divisions)) - ? 2 - : 1, - child: Container(alignment: widget.textAlign, child: text)); - }); - if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT || - widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) - widgets = widgets.reversed.toList(); - return widgets; - } - - Widget _getIndicators(_SideEnum side) { - return Expanded( - flex: (widget.indicatorStyle == BarGraphIndicatorStyle.BOTH) - ? ((100 - widget.textFlex) ~/ 2) - : (100 - widget.textFlex), - child: _getVerticalHorizontalSubWidget(_getBar())); - } - - List _getBar() { - List widgets = List.generate(widget.divisions + 1, (index) { - return Container( - color: (widget.indicatorsColor != null - ? widget.indicatorsColor - : Theme.of(context).buttonColor), - width: (widget.orientation == - BarGraphOrientation.HORIZONTAL_FROM_LEFT || - widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) - ? 3 - : null, - height: (widget.orientation == BarGraphOrientation.VERTICAL_FROM_TOP || - widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) - ? 3 - : null, - ); - }); - if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT || - widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) - widgets = widgets.reversed.toList(); - return widgets; - } - - Widget _getLabelAndBar() { - List children = []; - if (widget.indicatorStyle == BarGraphIndicatorStyle.BOTH || - widget.indicatorStyle == BarGraphIndicatorStyle.ONLY_LEFT_OR_TOP) - children.add(_getIndicators(_SideEnum.LEFT)); - - children.add(Expanded( - flex: widget.textFlex, - child: _getVerticalHorizontalTextWidget(_getLabels()), - )); - if (widget.indicatorStyle == BarGraphIndicatorStyle.BOTH || - widget.indicatorStyle == BarGraphIndicatorStyle.ONLY_RIGHT_OR_BOTTOM) - children.add(_getIndicators(_SideEnum.RIGHT)); - return _getVerticalHorizontalPrincipalWidget(children); - } - - int _getProgressQuarterTurns() { - if (widget.orientation == BarGraphOrientation.VERTICAL_FROM_TOP || - widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) - return 1; - else - return 0; - } - - Alignment _getProgressAlignment() { - switch (widget.orientation) { - case BarGraphOrientation.HORIZONTAL_FROM_LEFT: - return Alignment.topLeft; - case BarGraphOrientation.HORIZONTAL_FROM_RIGHT: - return Alignment.topRight; - case BarGraphOrientation.VERTICAL_FROM_TOP: - return Alignment.topLeft; - case BarGraphOrientation.VERTICAL_FROM_BOTTOM: - return Alignment.bottomLeft; - default: - return Alignment.topLeft; - } - } - - @override - void dispose() { - _animationController.dispose(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - _updateValue(); - return Stack(children: [ - Container( - color: (widget.backgroundColor != null - ? widget.backgroundColor - : Theme.of(context).scaffoldBackgroundColor), - ), - Container( - alignment: _getProgressAlignment(), - child: RotatedBox( - quarterTurns: _getProgressQuarterTurns(), - child: FractionallySizedBox( - widthFactor: _actualProgress(), - heightFactor: 1, - child: Container( - color: (widget.barColor != null - ? widget.barColor - : Theme.of(context).primaryColor), - ), - ), - ), - ), - Container(child: _getLabelAndBar()), - ]); - } -} +export 'src/bargraph.dart'; diff --git a/lib/src/bargraph.dart b/lib/src/bargraph.dart new file mode 100644 index 0000000..eb2f621 --- /dev/null +++ b/lib/src/bargraph.dart @@ -0,0 +1,381 @@ +library flutter_bargraph; + +import 'package:flutter/material.dart'; + +/// [BarGraphOrientation] Enum +enum BarGraphOrientation { + /// Bar orientation Vertical top to bottom + VERTICAL_FROM_TOP, + + /// Bar orientation Vertical bottom to top + VERTICAL_FROM_BOTTOM, + + /// Bar orientation Horizontal left to right + HORIZONTAL_FROM_LEFT, + + /// Bar orientation Horizontal right to left + HORIZONTAL_FROM_RIGHT, +} + +/// [BarGraphIndicatorStyle] Enum +enum BarGraphIndicatorStyle { + /// View all indicator + BOTH, + + /// View only left/Top indicator + ONLY_LEFT_OR_TOP, + + /// View only Right/Bottom indicator + ONLY_RIGHT_OR_BOTTOM, + + /// Hidden all indicator + NOTHING +} + +/// [BarGraphIndicatorSpacing] Enum +enum BarGraphIndicatorSpacing { + /// Is indicator spacing type + SPACE_AROUND, + + /// Is indicator spacing type + SPACE_BETWEEN, +} + +class BarGraph extends StatefulWidget { + /// Is [backgroundColor] of BarGraph + /// + /// Default Theme.of(context).scaffoldBackgroundColor + final Color? backgroundColor; + + /// [barColor] is a color of BarGraph bar + /// + /// DefaultTheme.of(context).primaryColor + final Color barColor; + + /// [indicatorsColor] is a color of BarGraph line indicator + /// + /// Default: Theme.of(context).buttonColor + final Color indicatorsColor; + + /// [textStyle] is a TextStyle of BarGraph text label indicator + /// + /// Default: Text Widget default TextStyle + final TextStyle? textStyle; + + /// [textAlign] is a Alignment of BarGraph text label indicator + /// + /// Default: Alignment.center + final Alignment textAlign; + + /// [value] is actual value of BarGraph bar + /// + /// Default: 15 + final double value; + + /// [min] is min value of BarGraph scale + /// + /// Default: 0 + final double min; + + /// [max] is max value of BarGraph scale + /// + ///Default: 100 + final double max; + + /// [divisions] is count of BarGraph indicators + /// + /// Default: 10 + final int divisions; + + /// [fractionDigits] is number of digits of BarGraph text label indicator + /// + /// Default: 2 + final int fractionDigits; + + /// [animationDuration] is a millisecond of animation duration on changed value of BarGraph + /// + /// Default: 200 milliseconds + final int animationDuration; + + /// [textFlex] is the percentage of portion used for text, remaining space is used for indicators. + /// + ///Default: 20% + final int textFlex; + + /// [orientation] is a orientation of BarGraph + /// + /// Default: BarGraphOrientation.VERTICAL_FROM_BOTTOM + /// + /// Possible orientation: + /// * BarGraphOrientation.VERTICAL_FROM_TOP + /// * BarGraphOrientation.VERTICAL_FROM_BOTTOM + /// * BarGraphOrientation.HORIZONTAL_FROM_LEFT + /// * BarGraphOrientation.HORIZONTAL_FROM_RIGHT + final BarGraphOrientation orientation; + + /// [indicatorStyle] is the scale indicators style + /// + /// Default: BarGraphIndicatorStyle.BOTH, left and right visible. + /// + /// Possible orientation: + /// * BarGraphIndicatorStyle.BOTH + /// * BarGraphIndicatorStyle.ONLY_LEFT_OR_TOP + /// * BarGraphIndicatorStyle.ONLY_RIGHT_OR_BOTTOM + /// * BarGraphIndicatorStyle.NOTHING + final BarGraphIndicatorStyle indicatorStyle; + + /// [indicatorSpacing] is the scale indicators spacing + /// + /// Default: BarGraphIndicatorSpacing.SPACE_AROUND + /// + /// Possible orientation: + /// * BarGraphIndicatorSpacing.SPACE_AROUND + /// * BarGraphIndicatorSpacing.SPACE_BETWEEN + final BarGraphIndicatorSpacing indicatorSpacing; + + /// Creates an [BarGraph] + /// Material design's + BarGraph( + {Key? key, + this.backgroundColor, + this.barColor = Colors.blue, + this.indicatorsColor = Colors.grey, + this.textStyle, + this.textAlign = Alignment.center, + this.fractionDigits = 2, + this.value = 15, + this.divisions = 10, + this.min = 0, + this.max = 100, + this.animationDuration = 200, + this.orientation = BarGraphOrientation.VERTICAL_FROM_BOTTOM, + this.textFlex = 20, + this.indicatorStyle = BarGraphIndicatorStyle.BOTH, + this.indicatorSpacing = BarGraphIndicatorSpacing.SPACE_AROUND}) + : assert( + value >= min, 'The value is less than the specified minimum value'), + assert(value <= max, + 'The value is greater than the specified maximum value'), + assert(divisions > 0, 'Divisions must be greater than 0'), + assert(textFlex > 0 && textFlex < 100), + super(key: key); + + @override + _BarGraphState createState() => _BarGraphState(); +} + +enum _SideEnum { LEFT, RIGHT } + +class _BarGraphState extends State with TickerProviderStateMixin { + late Animation _animation; + late Tween _tween; + late AnimationController _animationController; + double _valueImg = 0; + + _BarGraphState(); + + @override + void initState() { + super.initState(); + _valueImg = widget.value; + _animationController = AnimationController( + duration: Duration(milliseconds: widget.animationDuration), + vsync: this); + _tween = Tween(begin: widget.min, end: widget.value); + _animation = _tween.animate(_animationController) + ..addListener(() { + setState(() {}); + }); + _animationController.forward(); + } + + void _updateValue() { + if (_valueImg != widget.value) { + _tween.begin = _animation.value; + _animationController.reset(); + _tween.end = widget.value; + _animationController.forward(); + _valueImg = widget.value; + } + } + + double _actualProgress() { + double progress = + (_animation.value - widget.min) / (widget.max - widget.min); + double offset = 0; + if (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND) + offset = ((1 / (widget.divisions + 1)) / 2); + return offset + (progress * (1 - (offset * 2))); + } + + Widget _getVerticalHorizontalPrincipalWidget(List children) { + if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_LEFT || + widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) + return Column( + children: children, + ); + else + return Row( + children: children, + ); + } + + Widget _getVerticalHorizontalSubWidget(List children) { + if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_LEFT || + widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) + return Row( + children: children, + mainAxisAlignment: + (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND) + ? MainAxisAlignment.spaceAround + : MainAxisAlignment.spaceBetween, + ); + else + return Column( + children: children, + mainAxisAlignment: + (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND) + ? MainAxisAlignment.spaceAround + : MainAxisAlignment.spaceBetween, + ); + } + + Widget _getVerticalHorizontalTextWidget(List children) { + if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_LEFT || + widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) + return Row( + children: children, + mainAxisAlignment: MainAxisAlignment.spaceAround, + ); + else + return Column( + children: children, + mainAxisAlignment: MainAxisAlignment.spaceAround, + ); + } + + List _getLabels() { + List widgets = List.generate(widget.divisions + 1, (index) { + Widget text; + if (widget.indicatorSpacing == BarGraphIndicatorSpacing.SPACE_AROUND || + (index > 0 && index < widget.divisions)) + text = Text( + (widget.min + + (index * ((widget.max - widget.min) / widget.divisions))) + .toStringAsFixed(widget.fractionDigits), + style: widget.textStyle); + else + text = Text(''); + + return Expanded( + flex: (widget.indicatorSpacing == + BarGraphIndicatorSpacing.SPACE_AROUND || + (index > 0 && index < widget.divisions)) + ? 2 + : 1, + child: Container(alignment: widget.textAlign, child: text)); + }); + if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT || + widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) + widgets = widgets.reversed.toList(); + return widgets; + } + + Widget _getIndicators(_SideEnum side) { + return Expanded( + flex: (widget.indicatorStyle == BarGraphIndicatorStyle.BOTH) + ? ((100 - widget.textFlex) ~/ 2) + : (100 - widget.textFlex), + child: _getVerticalHorizontalSubWidget(_getBar())); + } + + List _getBar() { + List widgets = List.generate(widget.divisions + 1, (index) { + return Container( + color: widget.indicatorsColor, + width: (widget.orientation == + BarGraphOrientation.HORIZONTAL_FROM_LEFT || + widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT) + ? 3 + : null, + height: (widget.orientation == BarGraphOrientation.VERTICAL_FROM_TOP || + widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) + ? 3 + : null, + ); + }); + if (widget.orientation == BarGraphOrientation.HORIZONTAL_FROM_RIGHT || + widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) + widgets = widgets.reversed.toList(); + return widgets; + } + + Widget _getLabelAndBar() { + List children = []; + if (widget.indicatorStyle == BarGraphIndicatorStyle.BOTH || + widget.indicatorStyle == BarGraphIndicatorStyle.ONLY_LEFT_OR_TOP) + children.add(_getIndicators(_SideEnum.LEFT)); + + children.add(Expanded( + flex: widget.textFlex, + child: _getVerticalHorizontalTextWidget(_getLabels()), + )); + if (widget.indicatorStyle == BarGraphIndicatorStyle.BOTH || + widget.indicatorStyle == BarGraphIndicatorStyle.ONLY_RIGHT_OR_BOTTOM) + children.add(_getIndicators(_SideEnum.RIGHT)); + return _getVerticalHorizontalPrincipalWidget(children); + } + + int _getProgressQuarterTurns() { + if (widget.orientation == BarGraphOrientation.VERTICAL_FROM_TOP || + widget.orientation == BarGraphOrientation.VERTICAL_FROM_BOTTOM) + return 1; + else + return 0; + } + + Alignment _getProgressAlignment() { + switch (widget.orientation) { + case BarGraphOrientation.HORIZONTAL_FROM_LEFT: + return Alignment.topLeft; + case BarGraphOrientation.HORIZONTAL_FROM_RIGHT: + return Alignment.topRight; + case BarGraphOrientation.VERTICAL_FROM_TOP: + return Alignment.topLeft; + case BarGraphOrientation.VERTICAL_FROM_BOTTOM: + return Alignment.bottomLeft; + default: + return Alignment.topLeft; + } + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + _updateValue(); + return Stack(children: [ + Container( + color: widget.backgroundColor, + ), + Container( + alignment: _getProgressAlignment(), + child: RotatedBox( + quarterTurns: _getProgressQuarterTurns(), + child: FractionallySizedBox( + widthFactor: _actualProgress(), + heightFactor: 1, + child: Container( + color: widget.barColor, + ), + ), + ), + ), + Container(child: _getLabelAndBar()), + ]); + } +} diff --git a/pubspec.lock b/pubspec.lock index ec140a6..0e00c78 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -143,5 +143,5 @@ packages: source: hosted version: "2.1.0" sdks: - dart: ">=2.12.0-0.0 <3.0.0" + dart: ">=2.12.0 <3.0.0" flutter: ">=1.17.0" diff --git a/pubspec.yaml b/pubspec.yaml index 04f5e0a..7d24b0f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,12 +1,12 @@ name: flutter_bargraph description: Bar Graph Indicator for Flutter. It graphically displays the current value on a bar graph with animation when the value changes. orientation/direction of the bar is castumizable. -version: 1.0.0 +version: 1.1.0 homepage: https://github.com/rickypid/flutter_bargraph repository: https://github.com/rickypid/flutter_bargraph issue_tracker: https://github.com/rickypid/flutter_bargraph/issues environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" flutter: ">=1.17.0" dependencies: @@ -17,39 +17,4 @@ dev_dependencies: flutter_test: sdk: flutter -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. flutter: - - # To add assets to your package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/custom-fonts/#from-packages diff --git a/test/flutter_bargraph_test.dart b/test/flutter_bargraph_test.dart deleted file mode 100644 index 11b9419..0000000 --- a/test/flutter_bargraph_test.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; - -import 'package:flutter_bargraph/flutter_bargraph.dart'; - -void main() { - /* - test('adds one to input values', () { - final calculator = Calculator(); - expect(calculator.addOne(2), 3); - expect(calculator.addOne(-7), -6); - expect(calculator.addOne(0), 1); - }); - - */ -}