chart_sparkline 1.0.15+1 copy "chart_sparkline: ^1.0.15+1" to clipboard
chart_sparkline: ^1.0.15+1 copied to clipboard

Beautiful sparkline charts for Flutter.Average line, highest and lowest value.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:chart_sparkline/chart_sparkline.dart';
import 'package:flutter_hsvcolor_picker/flutter_hsvcolor_picker.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: const _Body(),
      ),
    ),
  );
}

class _Configs {
  final List<double> data;
  final bool averageLabel;
  final bool averageLine;
  final Color? backgroundColor;
  final Color lineColor;
  final FillMode fillMode;
  final Color fillColor;
  final PointsMode pointsMode;
  final int pointIndex;
  final double pointSize;
  final Color pointColor;

  const _Configs({
    required this.data,
    required this.averageLabel,
    required this.averageLine,
    required this.backgroundColor,
    required this.lineColor,
    required this.fillMode,
    required this.fillColor,
    required this.pointsMode,
    required this.pointIndex,
    required this.pointSize,
    required this.pointColor,
  });

  _Configs copyWith({
    List<double>? data,
    bool? averageLabel,
    bool? averageLine,
    Color? backgroundColor,
    Color? lineColor,
    FillMode? fillMode,
    Color? fillColor,
    PointsMode? pointsMode,
    int? pointIndex,
    double? pointSize,
    Color? pointColor,
  }) {
    return _Configs(
      data: data ?? this.data,
      averageLabel: averageLabel ?? this.averageLabel,
      averageLine: averageLine ?? this.averageLine,
      backgroundColor: backgroundColor ?? this.backgroundColor,
      lineColor: lineColor ?? this.lineColor,
      fillMode: fillMode ?? this.fillMode,
      fillColor: fillColor ?? this.fillColor,
      pointsMode: pointsMode ?? this.pointsMode,
      pointIndex: pointIndex ?? this.pointIndex,
      pointSize: pointSize ?? this.pointSize,
      pointColor: pointColor ?? this.pointColor,
    );
  }
}

class _ConfigsWidget extends StatelessWidget {
  final _Configs configs;
  final void Function(_Configs Function(_Configs)) onChanged;
  const _ConfigsWidget({
    Key? key,
    required this.configs,
    required this.onChanged,
  }) : super(key: key);

  void _toggleAverageLabel() {
    onChanged(
      (configs) => configs.copyWith(
        averageLabel: !configs.averageLabel,
      ),
    );

    if (configs.averageLabel && !configs.averageLine) {
      onChanged(
        (configs) => configs.copyWith(
          averageLine: true,
        ),
      );
    }
  }

  void _toggleAverageLine() {
    onChanged(
      (configs) => configs.copyWith(
        averageLine: !configs.averageLine,
      ),
    );

    if (!configs.averageLine) {
      onChanged(
        (configs) => configs.copyWith(averageLabel: false),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Row(
          children: [
            Text('averageLabel'),
            Switch(
              value: configs.averageLabel,
              onChanged: (value) {
                _toggleAverageLabel();
              },
            ),
          ],
        ),
        Row(
          children: [
            Text('averageLine'),
            Switch(
              value: configs.averageLine,
              onChanged: (value) {
                _toggleAverageLine();
              },
            ),
          ],
        ),
        _PickColorButton(
          title: 'Pick background color',
          color: configs.backgroundColor,
          onChanged: (newColor) => onChanged(
            (configs) => configs.copyWith(
              backgroundColor: newColor,
            ),
          ),
        ),
        SizedBox(
          height: 10,
        ),
        _PickColorButton(
          title: 'Pick line color',
          color: configs.lineColor,
          onChanged: (newColor) => onChanged(
            (configs) => configs.copyWith(
              lineColor: newColor,
            ),
          ),
        ),
        Row(
          children: [
            Container(child: Text('fillMode')),
            ...FillMode.values.map(
              (fillMode) {
                return Row(
                  children: [
                    Radio<FillMode>(
                      value: fillMode,
                      groupValue: configs.fillMode,
                      onChanged: (value) {
                        onChanged(
                          (configs) => configs.copyWith(
                            fillMode: value,
                          ),
                        );
                      },
                    ),
                    Text(
                      fillMode.name,
                    ),
                  ],
                );
              },
            ).toList(),
          ],
        ),
        if (configs.fillMode != FillMode.none)
          _PickColorButton(
            title: 'Pick fill color',
            color: configs.fillColor,
            onChanged: (newColor) => onChanged(
              (configs) => configs.copyWith(
                fillColor: newColor,
              ),
            ),
          ),
        Row(
          children: [
            Container(child: Text('pointsMode')),
            ...PointsMode.values.map(
              (pointsMode) {
                return Row(
                  children: [
                    Radio<PointsMode>(
                      value: pointsMode,
                      groupValue: configs.pointsMode,
                      onChanged: (value) {
                        onChanged(
                          (configs) => configs.copyWith(
                            pointsMode: value,
                          ),
                        );
                      },
                    ),
                    Text(
                      pointsMode.name,
                    ),
                  ],
                );
              },
            ).toList(),
          ],
        ),
        if (configs.pointsMode == PointsMode.atIndex)
          Row(
            children: [
              Text('pointIndex'),
              SizedBox(
                width: 200,
                child: Slider(
                  label: configs.pointIndex.toString(),
                  divisions: configs.data.length - 1,
                  value: configs.pointIndex + .0,
                  min: 0,
                  max: configs.data.length - 1,
                  onChanged: (value) {
                    onChanged(
                      (configs) => configs.copyWith(
                        pointIndex: value.toInt(),
                      ),
                    );
                  },
                ),
              ),
            ],
          ),
        if (configs.pointsMode != PointsMode.none) ...[
          Row(
            children: [
              Text('pointSize'),
              SizedBox(
                width: 200,
                child: Slider(
                  label: configs.pointSize.toString(),
                  divisions: 100,
                  value: configs.pointSize + .0,
                  min: 0,
                  max: 100,
                  onChanged: (value) {
                    onChanged(
                      (configs) => configs.copyWith(
                        pointSize: value,
                      ),
                    );
                  },
                ),
              ),
            ],
          ),
          _PickColorButton(
            title: 'Pick point color',
            color: configs.pointColor,
            onChanged: (newColor) => onChanged(
              (configs) => configs.copyWith(
                pointColor: newColor,
              ),
            ),
          ),
        ],
      ],
    );
  }
}

class _PickColorButton extends StatelessWidget {
  const _PickColorButton({
    Key? key,
    required this.title,
    required this.color,
    required this.onChanged,
  }) : super(key: key);

  final String title;
  final Color? color;
  final void Function(Color) onChanged;

  @override
  Widget build(BuildContext context) {
    final onPressed = () {
      final pickerWidget = Container(
        width: 600,
        child: ColorPicker(
          color: color ?? Colors.white,
          onChanged: onChanged,
        ),
      );

      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('Pick background color'),
            content: pickerWidget,
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: Text('OK'),
              ),
            ],
          );
        },
      );
    };

    return Row(
      children: [
        InkWell(
          onTap: onPressed,
          child: Container(
            width: 20,
            height: 20,
            decoration: BoxDecoration(
              color: color,
              border: Border.all(
                // if color is bright, use black as border color
                // if color is dark, use white as border color
                color: color == null
                    ? Colors.white
                    : color!.computeLuminance() > 0.5
                        ? Colors.black
                        : Colors.white,
                width: 1,
              ),
              borderRadius: BorderRadius.circular(10),
            ),
          ),
        ),
        SizedBox(
          width: 20,
        ),
        ElevatedButton(
          onPressed: onPressed,
          child: Text(title),
        ),
      ],
    );
  }
}

class _Body extends StatefulWidget {
  const _Body({
    Key? key,
  }) : super(key: key);

  @override
  State<_Body> createState() => _BodyState();
}

class _BodyState extends State<_Body> {
  var _configs = const _Configs(
    data: [-1.5, 1 - 0, 2 - 5, -1.5, 2, 5, -2.3],
    averageLabel: false,
    averageLine: false,
    backgroundColor: null,
    lineColor: Colors.lightBlue,
    fillMode: FillMode.none,
    fillColor: const Color(0xFF81D4FA),
    pointsMode: PointsMode.none,
    pointIndex: 0,
    pointSize: 4.0,
    pointColor: const Color(0xFF0277BD),
  );

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(10.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Expanded(
            child: _ConfigsWidget(
              configs: _configs,
              onChanged: (value) {
                setState(() {
                  _configs = value(_configs);
                });
              },
            ),
          ),
          Expanded(
            child: _Graph(
              configs: _configs,
            ),
          ),
        ],
      ),
    );
  }
}

class _Graph extends StatelessWidget {
  const _Graph({
    Key? key,
    required _Configs configs,
  })  : _configs = configs,
        super(key: key);

  final _Configs _configs;

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: const BoxDecoration(
        border: Border(
          top: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
          left: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
          right: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
          bottom: BorderSide(width: 1.0, color: Color(0xFFFF000000)),
        ),
      ),
      width: 600.0,
      height: 250.0,
      child: Sparkline(
        data: _configs.data,
        averageLine: _configs.averageLine,
        averageLabel: _configs.averageLabel,
        backgroundColor: _configs.backgroundColor,
        lineColor: _configs.lineColor,
        fillMode: _configs.fillMode,
        fillColor: _configs.fillColor,
        pointsMode: _configs.pointsMode,
        pointIndex: _configs.pointIndex,

        pointSize: _configs.pointSize,
        pointColor: _configs.pointColor,
        // useCubicSmoothing: true,
        // lineWidth: 1.0,
        // gridLinelabelPrefix: '\$',
        // gridLineLabelPrecision: 3,
        // enableGridLines: true,
        // kLine: ['max', 'min', 'first', 'last'],
        // // max: 50.5,
        // // min: 10.0,
        // enableThreshold: true,
        // thresholdSize: 0.1,
        // lineGradient: LinearGradient(
        //   begin: Alignment.topCenter,
        //   end: Alignment.bottomCenter,
        //   colors: [Colors.purple[800]!, Colors.purple[200]!],
        // ),
        // fillGradient: LinearGradient(
        //   begin: Alignment.topCenter,
        //   end: Alignment.bottomCenter,
        //   colors: [Colors.red[800]!, Colors.red[200]!],
        // ),
      ),
    );
  }
}
100
likes
130
pub points
95%
popularity
screenshot

Publisher

verified publisherdev.sumsg.com

Beautiful sparkline charts for Flutter.Average line, highest and lowest value.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (LICENSE)

Dependencies

flutter

More

Packages that depend on chart_sparkline