In this blog you will get a quick overview of our Flutter Radial Gauge and its features by designing a speedometer mobile application.
The Radial Gauge for Flutter is a data visualization widget written in Dart that displays numerical values on a circular scale. It has a rich set of features such as axes, ranges, pointers, and annotations that are fully customizable and extendable. You can use this to design mobile applications that include a speedometer, temperature monitor, dashboard, multi-axis clock, watch, compass, and so on.
To design a speedometer, you need the following features in a radial gauge widget:
This section explains how to design a speedometer with a directional compass that indicates the current direction by customizing the appearance of the radial gauge. The fully developed application will appear as shown in the following screenshot.
Note: Dark theme mode is used for this demo app.
Create a simple project using the instructions given in the Get Started documentation on the Flutter website.
Add dependency
Add the Syncfusion Flutter Gauge dependency to your pubspec.yaml file.
dependencies: syncfusion_flutter_gauges: ^18.2.44
Get packages
Run the following command to get the required packages.
$ flutter pub get
Import package
Import the following package in your Dart code.
import 'package:syncfusion_flutter_gauges/gauges.dart';
After the package has been imported, initialize the SfRadialGauge as a child of any widget, such as a container widget.
The first step in designing a speedometer is to add speed scale values as numbers from the minimum, 0, to the maximum, 200, with a specific interval. This can be achieved using the axes in the radial gauge.
Axes contain a collection of axis elements, and you can add any number of radial axes inside the gauge. In the Radial Gauge, you can display the speedometer labels from 0 to 200 using the minimum and maximum properties and customize their style using the axisLabelStyle property.
Axes have two types of tick marks: major and minor. Major ticks have labels and are used to specify the primary value intervals. Minor ticks do not have labels and are used to define the secondary value interval. You can specify the ticks’ appearance and position-related properties using the majorTickStyle and minorTickStyle properties for the axis.
SfRadialGauge( axes: <RadialAxis>[ RadialAxis(minimum: 0, maximum: 200, labelOffset: 30, axisLineStyle: AxisLineStyle( thicknessUnit: GaugeSizeUnit.factor,thickness: 0.03), majorTickStyle: MajorTickStyle(length: 6,thickness: 4,color: Colors.white), minorTickStyle: MinorTickStyle(length: 3,thickness: 3,color: Colors.white), axisLabelStyle: GaugeTextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 14 ) ) ] )
Next, we’ll add speed alerts in the form of color indicators of how fast a person is traveling. The green end of the color range will indicate a safe speed, the yellow color range will indicate a precarious speed, and the red color range will indicate a dangerous, high speed. To achieve this, we’ll use the range support in the Radial Gauge widget.
A range is a visual element that helps you visualize where a value falls on a radial scale. You can set color indicators as either a single range with a gradient or multiple ranges. In this blog, we’ll use a range with a gradient that contains three colors.
Every range has start and end values, and these can be specified using the startValue and endValue properties. The width of a range can be customized using the startWidth and endWidth properties.
ranges: <GaugeRange>[ GaugeRange(startValue: 0, endValue: 200, sizeUnit: GaugeSizeUnit.factor,startWidth: 0.03,endWidth: 0.03, gradient: SweepGradient( colors: const<Color>[Colors.green,Colors.yellow,Colors.red], stops: const<double>[0.0,0.5,1]))],
Next, we need to add a needle pointer to indicate the speed in the speedometer. This can be achieved using the pointer support in the Radial Gauge.
A needle pointer will be used to design the value indication symbol and point out the current value. Add the needle pointer in the Pointers collection and customize its length, size, and knob style.
pointers: <GaugePointer>[NeedlePointer(value:_value, needleLength: 0.95, enableAnimation: true, animationType: AnimationType.ease, needleStartWidth: 1.5, needleEndWidth: 6, needleColor: Colors.red, knobStyle: KnobStyle(knobRadius: 0.09))],
Finally, we need to display the current speed value at the bottom of the speedometer. This can be achieved using the annotation support in the Radial Gauge.
Using annotations, you can add text widgets over the gauge to display the current pointer value and measurement info. The position of annotations can be customized using the angle and positionFactor properties.
annotations: <GaugeAnnotation>[ GaugeAnnotation(widget: Container(child: Column( children: <Widget>[ Text(_value.toString(), style: TextStyle(fontSize: 25,fontWeight: FontWeight.bold)), SizedBox(height: 20), Text('mph', style: TextStyle(fontSize: 14,fontWeight: FontWeight.bold))] )), angle: 90, positionFactor: 0.75)]
Additionally, you can add a directional compass to the speedometer to show the current direction of travel. This will increase the functionality of the speedometer app. To implement a compass, we will add another axis inside the Radial Gauge widget using the Axes property. This axis will be included behind the main axis at the 0 index in the axes collection so that the needle pointer will be displayed on top as shown in the following figure.
axes: <RadialAxis>[ RadialAxis(startAngle: 270, endAngle: 270,minimum: 0,maximum: 80,interval: 10,radiusFactor: 0.4, showAxisLine: false, showLastLabel: false, minorTicksPerInterval: 4, majorTickStyle: MajorTickStyle(length: 8,thickness: 3,color: Colors.white), minorTickStyle: MinorTickStyle(length: 3,thickness: 1.5,color: Colors.grey), axisLabelStyle: GaugeTextStyle(color: Colors.white,fontWeight: FontWeight.bold,fontSize: 14 ), onLabelCreated: labelCreated), RadialAxis()]
In the previous figure, the axis labels are displayed from 0 to 80 with an interval of 20. In the directional compass, we need to define string labels that denote corresponding directions. So, we will customize the numeric axis labels using the onLabelCreated event in the axis to note the north, east, south, and west directions.
axes: <RadialAxis>[ RadialAxis(startAngle: 270, endAngle: 270,minimum: 0,maximum: 80,interval: 10,radiusFactor: 0.4, onLabelCreated: labelCreated), RadialAxis()]
void labelCreated(AxisLabelCreatedArgs args) { if(args.text =='0') { args.text = 'N'; args.labelStyle=GaugeTextStyle(color: Colors.red,fontWeight: FontWeight.bold,fontSize: 14); } else if(args.text=='10') args.text=''; else if(args.text=='20') args.text='E'; else if(args.text=='30') args.text=''; else if(args.text=='40') args.text='S'; else if(args.text=='50') args.text=''; else if(args.text=='60') args.text='W'; else if(args.text=='70') args.text=''; }
In a real-time speedometer app, data may be fetched from a data service or device GPS to update the pointer value. For this demo, data will be updated using a timer with a 1-second duration, and the app state will be changed to rebuild the widgets. The _value double variable is used to set the pointer value and the annotation’s text value. In each time tick, the _value variable is assigned with some random value in the setState callback as shown in the following code to update the pointer and annotation text value.
_timer = Timer.periodic(const Duration(milliseconds: 1000),(_timer) { setState(() { _value = (Random().nextDouble() * 40) + 60; }); });
You can download the complete sample code from this GitHub location.
The Syncfusion Radial Gauge widget for Flutter has been designed with flexible UI customization options to make adapting your app easy. It includes developer-friendly APIs to increase productivity.
Feel free to browse the Radial Gauge documentation to learn more about its features and APIs. You can also see Syncfusion’s Flutter app with many examples in this GitHub repo. Don’t miss our demo app in Google Play and the App Store.
Also, if you need a new widget for the Flutter framework that we don’t offer currently, please let us know in the comments section below. You can also contact us through our support forum, Direct-Trac, or feedback portal. As always, we are happy to assist you!