How to Implementing Gauge Indicator in Flutter Package?

Spread the love

 

 

 

Implementing Gauge Indicator in Flutter Package
Implementing Gauge Indicator in Flutter Package
Implementing Gauge Indicator in Flutter Package two
Implementing Gauge Indicator in Flutter Package two

Introduction

The gauge_indicator package allows you to create gauge indicators, which are graphical representations of a value within a range. This guide will show you how to integrate and use this package to create gauge indicators in your Flutter app.

Content

1.Add the gauge_indicator dependency:

Open your pubspec.yaml file and add the gauge_indicator dependency.


dependencies:
  gauge_indicator: ^latest_version

Run flutter pub get to install the package.

 

2.Import the package:

Import the gauge_indicator package in your Dart file.


import 'package:gauge_indicator/gauge_indicator.dart';

3.Create a gauge indicator:

Use the GaugeIndicator widget to create a gauge indicator.


GaugeIndicator(
  value: 0.5,
  minValue: 0,
  maxValue: 1,
  gaugeColor: Colors.grey,
  indicatorColor: Colors.blue,
  labelText: 'Progress',
)

Customize the value, minValue, maxValue, gaugeColor, indicatorColor, and labelText parameters as needed. The value parameter represents the value to be displayed on the gauge indicator, and the minValue and maxValue parameters define the range of the gauge. The gaugeColor parameter sets the color of the gauge, while the indicatorColor parameter sets the color of the indicator. The labelText parameter sets the text label to be displayed below the gauge.

 

4.Run the app:

Run your Flutter app to see the gauge indicator. It should display the value within the specified range with the gauge and indicator colors as set.

 

Sample Code


// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:gauge_indicator/gauge_indicator.dart';

class GaugeIndicatorWidget extends StatelessWidget {
  const GaugeIndicatorWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 1,
        centerTitle: true,
        title: Text(
          "Gauge indicator",
          style: TextStyle(color: Colors.black, fontWeight: FontWeight.w700, fontSize: 22),
        ),
        backgroundColor: Color.fromARGB(255, 27, 255, 255),
      ),
      body: Center(
        child: AnimatedRadialGauge(
          duration: const Duration(seconds: 1),
          curve: Curves.elasticOut,
          radius: 130,
          value: 32,
          axis: const GaugeAxis(
            min: 10,
            max: 120,
            degrees: 230,
            style: GaugeAxisStyle(
              thickness: 40,
              background: Color(0xFFDFE2EC),
              segmentSpacing: 24,
            ),
            pointer: GaugePointer.needle(
              color: Colors.black,
              height: 83,
              width: 23,
              borderRadius: 20,
            ),
            progressBar: GaugeProgressBar.rounded(
              color: Color.fromARGB(255, 50, 80, 197),
            ),
            segments: [
              GaugeSegment(
                from: 33,
                to: 33.3,
                color: Color(0xFFD9DEEB),
                cornerRadius: Radius.zero,
              ),
              GaugeSegment(
                from: 33.3,
                to: 66.6,
                color: Color(0xFFD9DEEB),
                cornerRadius: Radius.zero,
              ),
              GaugeSegment(
                from: 66.6,
                to: 100,
                color: Color(0xFFD9DEEB),
                cornerRadius: Radius.zero,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Output

Implementing Gauge Indicator in Flutter Package
Implementing Gauge Indicator in Flutter Package

 

Sample Code – 2


import 'package:flutter/material.dart';
import 'package:flutter_one/views/gauge_indicator/gauge_indicator.dart';

import 'package:gauge_indicator/gauge_indicator.dart';

import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'dart:math' as math show Random;

import 'dart:math' as math;

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Radial gauge',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        tabBarTheme: const TabBarTheme(
          labelColor: Colors.black,
        ),
      ),
      home: const Scaffold(
        body: RadialGaugeExamplePage(),
      ),
    );
  }
}

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

  @override
  State<RadialGaugeExamplePage> createState() => _RadialGaugeExamplePageState();
}

class _RadialGaugeExamplePageState extends State<RadialGaugeExamplePage> {
  final _controller = GaugeDataController();

  @override
  Widget build(BuildContext context) {
    final viewSize = MediaQuery.sizeOf(context);
    final isMobile = viewSize.width < 700;

    return Scaffold(
      body: Builder(builder: (context) {
        final gaugeWidget = Center(
          child: AnimatedBuilder(
            animation: _controller,
            builder: (context, _) => Container(
              decoration: BoxDecoration(
                border: Border.all(
                  color: const Color(0xFFEFEFEF),
                ),
              ),
              width: _controller.parentWidth,
              height: _controller.parentHeight,
              child: AnimatedRadialGauge(
                radius: _controller.gaugeRadius,
                builder: _controller.hasPointer && _controller.pointerType == PointerType.needle
                    ? null
                    : (context, _, value) => RadialGaugeLabel(
                          style: TextStyle(
                            color: const Color(0xFF002E5F),
                            fontSize: _controller.fontSize,
                            fontWeight: FontWeight.bold,
                          ),
                          value: value,
                        ),
                duration: const Duration(milliseconds: 2000),
                curve: Curves.elasticOut,
                value: _controller.value,
                axis: GaugeAxis(
                  min: 0,
                  max: 100,
                  degrees: _controller.degree,
                  pointer: _controller.hasPointer ? _controller.getPointer(_controller.pointerType) : null,
                  progressBar: _controller.hasProgressBar ? _controller.getProgressBar(_controller.progressBarType) : null,
                  transformer: const GaugeAxisTransformer.colorFadeIn(
                    interval: Interval(0.0, 0.3),
                    background: Color(0xFFD9DEEB),
                  ),
                  style: GaugeAxisStyle(
                    thickness: _controller.thickness,
                    background: _controller.backgroundColor,
                    segmentSpacing: _controller.spacing,
                    blendColors: false,
                    cornerRadius: Radius.circular(_controller.segmentsRadius),
                  ),
                  segments: _controller.segments.map((e) => e.copyWith(cornerRadius: Radius.circular(_controller.segmentsRadius))).toList(),
                ),
              ),
            ),
          ),
        );

        if (isMobile) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.start,
            mainAxisSize: MainAxisSize.max,
            children: [
              const PageTitle(title: 'gauge_indicator', isSmall: true),
              Expanded(
                child: gaugeWidget,
              ),
              SizedBox(
                height: math.min(viewSize.height * 0.6, 400),
                child: DecoratedBox(
                  decoration: BoxDecoration(
                    color: Theme.of(context).scaffoldBackgroundColor,
                    border: const Border(top: BorderSide(color: Color(0xFFDDDDDD))),
                  ),
                  child: GaugeConfigPanel(controller: _controller),
                ),
              ),
            ],
          );
        } else {
          return Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                decoration: const BoxDecoration(
                  border: Border(right: BorderSide(color: Color(0xFFDDDDDD))),
                ),
                width: 350,
                child: Column(
                  children: [
                    const PageTitle(title: 'gauge_indicator'),
                    Expanded(
                      child: GaugeConfigPanel(controller: _controller),
                    ),
                  ],
                ),
              ),
              Expanded(child: gaugeWidget),
            ],
          );
        }
      }),
    );
  }
}

class GaugeConfigPanel extends StatelessWidget {
  final GaugeDataController _controller;

  const GaugeConfigPanel({
    Key? key,
    required GaugeDataController controller,
  })  : _controller = controller,
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, _) => ListView(
        padding: const EdgeInsets.symmetric(vertical: 24),
        children: [
          ValueSlider(
            label: "Value",
            min: 0,
            max: 100,
            value: _controller.sliderValue,
            onChanged: (val) {
              _controller.sliderValue = double.parse(val.toStringAsFixed(2));
            },
            onChangeEnd: (newVal) {
              _controller.value = newVal;
            },
          ),
          ValueSlider(
            label: "Degrees",
            min: 30,
            max: 360,
            value: _controller.degree,
            onChanged: (val) {
              _controller.degree = double.parse(val.toStringAsFixed(2));
            },
          ),
          ValueSlider(
            label: "Segments radius",
            min: 0,
            max: 20,
            value: _controller.segmentsRadius,
            onChanged: (val) {
              _controller.segmentsRadius = double.parse(val.toStringAsFixed(2));
            },
          ),
          ValueSlider(
            label: "Thickness",
            min: 5,
            max: 40,
            value: _controller.thickness,
            onChanged: (val) {
              _controller.thickness = double.parse(val.toStringAsFixed(2));
            },
          ),
          ValueSlider(
            label: "Spacing",
            min: 0,
            max: 20,
            value: _controller.spacing,
            onChanged: (val) {
              _controller.spacing = double.parse(val.toStringAsFixed(2));
            },
          ),
          ValueSlider(
            label: "Font size",
            min: 8,
            max: 48,
            value: _controller.fontSize,
            onChanged: (val) {
              _controller.fontSize = double.parse(val.toStringAsFixed(2));
            },
          ),
          ValueSlider(
            label: "Gauge radius",
            min: 50,
            max: 250,
            value: _controller.gaugeRadius,
            onChanged: (val) {
              _controller.gaugeRadius = double.parse(val.toStringAsFixed(2));
            },
          ),
          ValueSlider(
            label: "Parent height",
            min: 150,
            max: 500,
            value: _controller.parentHeight,
            onChanged: (val) {
              _controller.parentHeight = double.parse(val.toStringAsFixed(2));
            },
          ),
          ValueSlider(
            label: "Parent width",
            min: 150,
            max: 500,
            value: _controller.parentWidth,
            onChanged: (val) {
              _controller.parentWidth = double.parse(val.toStringAsFixed(2));
            },
          ),
          const Divider(),
          ColorField(
            title: "Background color",
            color: _controller.backgroundColor,
            onColorChanged: (c) => _controller.backgroundColor = c,
          ),
          ColorField(
            title: "Segment 1 color",
            color: _controller.segments[0].color,
            onColorChanged: (c) => _controller.setSegmentColor(0, c),
          ),
          ColorField(
            title: "Segment 2 color",
            color: _controller.segments[1].color,
            onColorChanged: (c) => _controller.setSegmentColor(1, c),
          ),
          ColorField(
            title: "Segment 3 color",
            color: _controller.segments[2].color,
            onColorChanged: (c) => _controller.setSegmentColor(2, c),
          ),
          const Divider(),
          CheckboxListTile(
              title: const Text("Has progress bar"),
              value: _controller.hasProgressBar,
              onChanged: (selected) {
                if (selected != null) {
                  _controller.hasProgressBar = selected;
                }
              }),
          if (_controller.hasProgressBar)
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
              child: DropdownButton<GaugeProgressPlacement>(
                items: [
                  for (final val in GaugeProgressPlacement.values)
                    DropdownMenuItem(
                      child: Text("Placement: ${val.name}"),
                      value: val,
                    )
                ],
                value: _controller.progressBarPlacement,
                onChanged: (val) {
                  if (val == null) return;
                  _controller.progressBarPlacement = val;
                },
              ),
            ),
          if (_controller.hasProgressBar)
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
              child: DropdownButton<ProgressBarType>(
                items: [
                  for (final val in ProgressBarType.values)
                    DropdownMenuItem(
                      child: Text("Type: ${val.name}"),
                      value: val,
                    )
                ],
                value: _controller.progressBarType,
                onChanged: (val) {
                  if (val == null) return;
                  _controller.progressBarType = val;
                },
              ),
            ),
          if (_controller.hasProgressBar)
            ColorField(
              title: "Select progress bar color",
              color: _controller.progressBarColor,
              onColorChanged: (c) => _controller.progressBarColor = c,
            ),
          const Divider(),
          CheckboxListTile(
              title: const Text("Has pointer"),
              value: _controller.hasPointer,
              onChanged: (selected) async {
                if (selected != null) {
                  _controller.hasPointer = selected;
                }
              }),
          if (_controller.hasPointer)
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 16, 16, 0),
              child: DropdownButton<PointerType>(
                items: [
                  for (final val in PointerType.values)
                    DropdownMenuItem(
                      child: Text("Type: ${val.name}"),
                      value: val,
                    )
                ],
                value: _controller.pointerType,
                onChanged: (val) {
                  if (val == null) return;

                  _controller.pointerType = val;
                },
              ),
            ),
          if (_controller.hasPointer)
            Padding(
              padding: const EdgeInsets.only(top: 16.0),
              child: ValueSlider(
                label: "Pointer size",
                min: 16,
                max: 36,
                value: _controller.pointerSize,
                onChanged: (val) {
                  _controller.pointerSize = val;
                },
              ),
            ),
          if (_controller.hasPointer)
            ColorField(
              title: "Pointer color",
              color: _controller.pointerColor,
              onColorChanged: (c) => _controller.pointerColor = c,
            ),
          const Divider(),
          Center(
            child: ElevatedButton(
              onPressed: _controller.randomizeSegments,
              child: const Text("Randomize segments"),
            ),
          ),
        ],
      ),
    );
  }
}

Future<Color?> pickColor(BuildContext context, Color initialColor) {
  Color color = initialColor;
  return showDialog<Color>(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text('Pick a color'),
      content: SingleChildScrollView(
        child: ColorPicker(
          pickerColor: color,
          onColorChanged: (c) => color = c,
        ),
      ),
      actions: <Widget>[
        ElevatedButton(
          child: const Text('Select'),
          onPressed: () {
            Navigator.of(context).pop(color);
          },
        ),
      ],
    ),
  );
}

class ColorField extends StatelessWidget {
  final String title;
  final Color color;
  final ValueChanged<Color> onColorChanged;

  const ColorField({
    Key? key,
    required this.title,
    required this.color,
    required this.onColorChanged,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text(title),
      onTap: () => pickColor(
        context,
        color,
      ).then((color) {
        if (color != null) {
          onColorChanged(color);
        }
      }),
      trailing: Container(
        width: 40,
        height: 40,
        color: color,
      ),
    );
  }
}

class PageTitle extends StatelessWidget {
  final String title;
  final bool isSmall;

  const PageTitle({
    Key? key,
    required this.title,
    this.isSmall = false,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      width: double.infinity,
      padding: isSmall ? const EdgeInsets.all(4) : const EdgeInsets.all(16),
      decoration: const BoxDecoration(
          border: Border(
        bottom: BorderSide(
          color: Color(0xFFDDDDDD),
        ),
      )),
      child: Text(
        title,
        style: TextStyle(
          fontSize: isSmall ? 14 : 24,
        ),
      ),
    );
  }
}

class ValueSlider extends StatelessWidget {
  final String label;
  final double value;
  final ValueChanged<double> onChanged;
  final ValueChanged<double>? onChangeEnd;
  final double min;
  final double max;

  const ValueSlider({
    Key? key,
    required this.label,
    required this.onChanged,
    this.onChangeEnd,
    required this.value,
    required this.min,
    required this.max,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 24.0),
          child: Text(
            "$label: ${value.toStringAsFixed(2)}",
            style: const TextStyle(
              fontSize: 16,
            ),
          ),
        ),
        Slider(
          min: min,
          max: max,
          value: value,
          onChanged: onChanged,
          onChangeEnd: onChangeEnd,
        ),
      ],
    );
  }
}

enum PointerType { needle, triangle, circle }

enum ProgressBarType { rounded, basic }

const colors = [
  Colors.green,
  Color(0xFF34C759),
  Colors.amber,
  Colors.red,
  Colors.blue,
  Colors.blueAccent,
  Colors.lightBlue,
  Colors.grey,
  Colors.black,
  Color(0xFFD9DEEB),
];

class GaugeDataController extends ChangeNotifier {
  double _value = 65;
  double get value => _value;
  set value(double val) {
    if (val != value) {
      _value = val;
      notifyListeners();
    }
  }

  double _sliderValue = 65;
  double get sliderValue => _sliderValue;
  set sliderValue(double value) {
    if (sliderValue != value) {
      _sliderValue = value;
      notifyListeners();
    }
  }

  double _degree = 260;
  double get degree => _degree;
  set degree(double value) {
    if (degree != value) {
      _degree = value;
      notifyListeners();
    }
  }

  bool _hasPointer = true;
  bool get hasPointer => _hasPointer;
  set hasPointer(bool value) {
    if (value != hasPointer) {
      _hasPointer = value;
      notifyListeners();
    }
  }

  bool _hasProgressBar = true;
  bool get hasProgressBar => _hasProgressBar;
  set hasProgressBar(bool value) {
    if (value != hasProgressBar) {
      _hasProgressBar = value;
      notifyListeners();
    }
  }

  double _segmentsRadius = 8;
  double get segmentsRadius => _segmentsRadius;
  set segmentsRadius(double value) {
    if (value != segmentsRadius) {
      _segmentsRadius = value;
      notifyListeners();
    }
  }

  Color _progressBarColor = Colors.purple;
  Color get progressBarColor => _progressBarColor;
  set progressBarColor(Color value) {
    if (value != progressBarColor) {
      _progressBarColor = value;
      notifyListeners();
    }
  }

  Color _backgroundColor = Colors.transparent;
  Color get backgroundColor => _backgroundColor;
  set backgroundColor(Color value) {
    if (value != backgroundColor) {
      _backgroundColor = value;
      notifyListeners();
    }
  }

  Color _pointerColor = const Color(0xFF002E5F);
  Color get pointerColor => _pointerColor;
  set pointerColor(Color value) {
    if (value != pointerColor) {
      _pointerColor = value;
      notifyListeners();
    }
  }

  double _parentWidth = 500;
  double get parentWidth => _parentWidth;
  set parentWidth(double value) {
    if (value != parentWidth) {
      _parentWidth = value;
      notifyListeners();
    }
  }

  double _parentHeight = 500;
  double get parentHeight => _parentHeight;
  set parentHeight(double value) {
    if (value != parentHeight) {
      _parentHeight = value;
      notifyListeners();
    }
  }

  double _gaugeRadius = 150;
  double get gaugeRadius => _gaugeRadius;
  set gaugeRadius(double value) {
    if (value != gaugeRadius) {
      _gaugeRadius = value;
      notifyListeners();
    }
  }

  double _thickness = 35;
  double get thickness => _thickness;
  set thickness(double value) {
    if (value != thickness) {
      _thickness = value;
      notifyListeners();
    }
  }

  double _spacing = 8;
  double get spacing => _spacing;
  set spacing(double value) {
    if (value != spacing) {
      _spacing = value;
      notifyListeners();
    }
  }

  double _fontSize = 46;
  double get fontSize => _fontSize;
  set fontSize(double value) {
    if (value != fontSize) {
      _fontSize = value;
      notifyListeners();
    }
  }

  double _pointerSize = 26;
  double get pointerSize => _pointerSize;
  set pointerSize(double value) {
    if (value != pointerSize) {
      _pointerSize = value;
      notifyListeners();
    }
  }

  PointerType _pointerType = PointerType.needle;
  PointerType get pointerType => _pointerType;
  set pointerType(PointerType value) {
    if (value != pointerType) {
      _pointerType = value;
      notifyListeners();
    }
  }

  GaugeProgressPlacement _progressBarPlacement = GaugeProgressPlacement.inside;
  GaugeProgressPlacement get progressBarPlacement => _progressBarPlacement;
  set progressBarPlacement(GaugeProgressPlacement value) {
    if (value != progressBarPlacement) {
      _progressBarPlacement = value;
      notifyListeners();
    }
  }

  ProgressBarType _progressBarType = ProgressBarType.basic;
  ProgressBarType get progressBarType => _progressBarType;
  set progressBarType(ProgressBarType value) {
    if (value != progressBarType) {
      _progressBarType = value;
      notifyListeners();
    }
  }

  GaugePointer getPointer(PointerType pointerType) {
    switch (pointerType) {
      case PointerType.needle:
        return GaugePointer.needle(
          width: pointerSize * 0.625,
          height: pointerSize * 4,
          color: pointerColor,
          position: GaugePointerPosition.center(
            offset: Offset(0, pointerSize * 0.3125),
          ),
        );
      case PointerType.triangle:
        return GaugePointer.triangle(
          width: pointerSize,
          height: pointerSize,
          borderRadius: pointerSize * 0.125,
          color: pointerColor,
          position: GaugePointerPosition.surface(
            offset: Offset(0, thickness * 0.6),
          ),
          border: GaugePointerBorder(
            color: Colors.white,
            width: pointerSize * 0.125,
          ),
        );
      case PointerType.circle:
        return GaugePointer.circle(
          radius: pointerSize * 0.5,
          color: pointerColor,
          border: GaugePointerBorder(
            color: Colors.white,
            width: pointerSize * 0.125,
          ),
        );
    }
  }

  List<GaugeSegment> get segments => _segments;
  set segments(List<GaugeSegment> value) {
    if (value != segments) {
      _segments = value;
      notifyListeners();
    }
  }

  List<GaugeSegment> _segments = <GaugeSegment>[
    const GaugeSegment(
      from: 0,
      to: 60.0,
      color: Color(0xFFD9DEEB),
      cornerRadius: Radius.zero,
    ),
    const GaugeSegment(
      from: 60.0,
      to: 85.0,
      color: Color(0xFFD9DEEB),
      cornerRadius: Radius.zero,
    ),
    const GaugeSegment(
      from: 85.0,
      to: 100,
      color: Color(0xFFD9DEEB),
      cornerRadius: Radius.zero,
    ),
  ];

  void randomizeSegments() {
    final random = math.Random();
    final a = random.nextDouble() * 100;
    final b = random.nextDouble() * 100;
    final stops = a > b ? [b, a] : [a, b];
    segments = <GaugeSegment>[
      GaugeSegment(
        from: 0,
        to: stops[0],
        color: colors[random.nextInt(colors.length)],
        cornerRadius: Radius.zero,
      ),
      GaugeSegment(
        from: stops[0],
        to: stops[1],
        color: colors[random.nextInt(colors.length)],
        cornerRadius: Radius.zero,
      ),
      GaugeSegment(
        from: stops[1],
        to: 100,
        color: colors[random.nextInt(colors.length)],
        cornerRadius: Radius.zero,
      ),
    ];
  }

  GaugeProgressBar getProgressBar(ProgressBarType progressBarType) {
    switch (progressBarType) {
      case ProgressBarType.rounded:
        return GaugeProgressBar.rounded(
          color: progressBarColor,
          placement: progressBarPlacement,
        );
      case ProgressBarType.basic:
        return GaugeProgressBar.basic(
          color: progressBarColor,
          placement: progressBarPlacement,
        );
    }
  }

  void setSegmentColor(int index, Color color) {
    RangeError.checkValidIndex(index, segments);

    segments[index] = segments[index].copyWith(
      color: color,
    );

    notifyListeners();
  }
}

 

Output-2

Implementing Gauge Indicator in Flutter Package two
Implementing Gauge Indicator in Flutter Package two

Conclusion

By following these steps, you can easily integrate the gauge_indicator package into your Flutter app and create gauge indicators. This can be useful for displaying progress, levels, or any other value within a specified range in your app.

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *