Sleek circular slider for Flutter

Overview

Sleek circular slider/progress bar & spinner for Flutter

License: MITAuthor's website

A highly customizable circular slider/progress bar & spinner for Flutter.

Example 01 Example 02 Example 03 Example 04 Example 05 Example 06 Example 07 Example 08 Example 09 Example 10 Example 11 Example 12

Getting Started

Installation

Add

sleek_circular_slider : ^lastest_version

to your pubspec.yaml, and run

flutter packages get

in your project's root directory.

Basic Usage

Import it to your project file

import 'package:sleek_circular_slider/sleek_circular_slider.dart';

And add it in its most basic form like it:

final slider = SleekCircularSlider(
                      appearance: CircularSliderAppearance(),
                      onChange: (double value) {
                        print(value);
                      });

There are additional optional parameters one can initialize the slider with.

final slider = SleekCircularSlider(
  min: 0,
  max: 1000,
  initialValue: 426,
  onChange: (double value) {
    // callback providing a value while its being changed (with a pan gesture)
  },
  onChangeStart: (double startValue) {
    // callback providing a starting value (when a pan gesture starts)
  },
  onChangeEnd: (double endValue) {
    // ucallback providing an ending value (when a pan gesture ends)
  },
  innerWidget: (double value) {
    // use your custom widget inside the slider (gets a slider value from the callback)
  },
);

Use as a progress bar

Slider user's interaction will be disabled if there is either no [onChange] or [onChangeEnd] provided. That way one can use the widget not as a slider but as a progress bar.

final slider = SleekCircularSlider(
  appearance: CircularSliderAppearance(
    customWidths: CustomSliderWidths(progressBarWidth: 10)),
  min: 10,
  max: 28,
  initialValue: 14,
);

Use as a spinner

There is one more use case for the library. It's a spinner which can be shown to users while loading etc. In this mode the widget is not interactive and ignores all angles so there is no need to provide them.

final slider = SleekCircularSlider(
  appearance: CircularSliderAppearance(
    spinnerMode: true,
));

SleekCircularSlider parameters

Parameter Default Description
appearance CircularSliderAppearance A set of objects describing the slider look and feel.
min double 0 The minimum value the user can select. Must be less than or equal to max.
max double 100 The maximum value the user can select. Must be greater than or equal to min.
initialValue double 50 The initial value for this slider.
onChange OnChange(double value) Called during a drag when the user is selecting a new value for the slider by dragging.
onChangeStart OnChange(double value) Called when the user starts selecting a new value for the slider.
onChangeEnd OnChange(double value) Called when the user is done selecting a new value for the slider.
innerWidget Widget InnerWidget(double value) A custom widget to replace the build in text labels which can capture a slider value from the callback.

CircularSliderAppearance parameters

Parameter Default Description
size double 150 The width & height value for the slider.
startAngle double 150 The angle (in degrees) the slider begins with.
angleRange double 240 The angle range (in degrees) the slider reaches when maximum value set.
counterClockwise bool false The setting indicating direction of the widget.
customWidths CustomSliderWidths The object with a set of widths for the track, bar, shadow etc.
customColors CustomSliderColors The object with a set of colors for the track, bar, shadow etc.
infoProperties InfoProperties The object with a set of properties for internal labels displaying a current slider value.
animationEnabled bool true The setting indicating whether external changes of a slider value should be animated.
spinnerMode bool false The setting turning the widget into a spinner.
spinnerDuration int 1500 The spinner animation duration in miliseconds
animDurationMultiplier double 1.0 The multiplier of duration for the animation when value changed

CustomSliderWidths parameters

Parameter Default Description
trackWidth double progressBarWidth / 4 The width of the slider's track.
progressBarWidth double slider's size / 10 The width of the slider's progress bar.
shadowWidth double progressBarWidth * 1.4 The width of the slider's shadow.
handlerSize double progressBarWidth / 5 The size of the slider's handler.

CustomSliderColors parameters

Parameter Default Description
trackColor Color #DCBEFB The color of the slider's track.
trackColors List null The list of colors for the track's gradient.
trackGradientStartAngle double 0 The start angle for the track's gradient.
trackGradientEndAngle double 180 The end angle for the track's gradient.
progressBarColor Color The color of the slider's progress bar. Won't be used if the slider uses gradient progressBarColors != null
progressBarColors List [#1E003B, #EC008A, #6285DA] The list of colors for the progress bar's gradient.
gradientStartAngle double 0 The start angle for the progress bar's gradient.
gradientEndAngle double 180 The end angle for the progress bar's gradient.
dynamicGradient bool false The gradient angles will change dynamically with value changing. If true it will ignore both the grandientStartAngle and gradientEndAngle
dotColor Color #FFFFFF The color of the slider's handle.
hideShadow bool false The setting indicating whether the shadow should be showed.
shadowColor Color #2C57C0 The color of the shadow.
shadowMaxOpacity double 0.2 The opacity of the shadow in its darker part.
shadowStep double The shadow is being painted with a number of steps. This value determines how big is a width of each step. The more steps are painted the softer the shadow is. For a flat shadow use a difference between the shadowWidth and the progressWidth for the shadowStep.

InfoProperties parameters

Parameter Default Description
mainLabelStyle TextStyle The text style of the main text widget displaying a slider's current value.
topLabelStyle TextStyle The text style of the top text widget.
bottomLabelStyle TextStyle The text style of the bottom text widget.
topLabelText String The text for the top text widget.
bottomLabelText String The text for the bottom text widget.
modifier String PercentageModifier(double percentage) closure adding the % character The closure allowing to modify how a current value of the slider is displayed.

Example of the modifier

String percentageModifier(double value) {
   final roundedValue = value.ceil().toInt().toString();
   return '$roundedValue %';
 }

It will convert a current value to int and add the % sufix to it.

YouTube video

YouTube Video of the example in action

Todo

  • add divisions

  • add more comments to document the code

  • add the counterclockwise direction

  • add the spinner mode

  • add the second handle (interval selection)

  • add text labels on a curved path

Acknowledgments

  • Hat tip to David Anaya for his awesome blog post about building a circular slider in Flutter and radian to degrees conversions which helped me a lot!
Comments
  • Null Safety

    Null Safety

    Now that flutter released 2.0, I think most developers will upgrade. Would be nice to have this lib updated with null-safety so people using it can migrate.

    opened by martin-dimi 9
  • Tap on circle without a track should not be registered as a tap

    Tap on circle without a track should not be registered as a tap

    I'm not sure if this is intended or not, but when I tap on the circle where no track is drawn I expect it to be ignored. Is this intended, a bug, or am I doing something wrong?

    This is my code.

    SleekCircularSlider(
                appearance: CircularSliderAppearance(
                  animationEnabled: false,
                  size: 300,
                  customWidths: CustomSliderWidths(
                    handlerSize: 20,
                    trackWidth: 10,
                    shadowWidth: 0,
                    progressBarWidth: 10,
                  ),
                  customColors: CustomSliderColors(
                    dotColor: Theme.of(context).accentColor,
                    trackColor: Theme.of(context).disabledColor,
                    progressBarColors: temperatureGradient.colors.reversed
                        .toList(),
                  ),
                ),
                innerWidget: (sliderValue) => SliderInnerWidget(sliderValue),
                min: 8,
                max: 28,
                initialValue: climateControllerHelper.setpoint,
                onChange: (v) {
                  LOG.info("Change: $v");
                },
                onChangeStart: (v) {
                  LOG.info("Start: $v");
                },
                onChangeEnd: (double value) {
                  doThings(value);
                },
              )
    
    opened by cirediew 6
  • UnimplementedError Flutter WEB

    UnimplementedError Flutter WEB

    I'm trying to run the example project and I'm getting this error:

    ══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════
    The following UnimplementedError was thrown during a scheduler callback:
    UnimplementedError
    
    When the exception was thrown, this was the stack:
    package:dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 196:49  throw_
    package:build_web_compilers/lib/_engine/engine/shader.dart 51:5                       createPaintStyle
    package:build_web_compilers/lib/_engine/engine/bitmap_canvas.dart 212:23              [_applyPaint]
    package:build_web_compilers/lib/_engine/engine/bitmap_canvas.dart 343:5               drawPath
    package:build_web_compilers/lib/_engine/engine/surface/recording_canvas.dart 990:11   apply
    package:build_web_compilers/lib/_engine/engine/surface/recording_canvas.dart 78:18    apply
    package:build_web_compilers/lib/_engine/engine/surface/picture.dart 253:35            paintCallback
    package:build_web_compilers/lib/_engine/engine/surface/surface.dart 71:14             commitScene
    package:build_web_compilers/lib/_engine/engine/surface/scene_builder.dart 520:5       build
    package:flutter/src/rendering/layer.dart 801:35                                       buildScene
    package:flutter/src/rendering/view.dart 230:36                                        compositeFrame
    package:flutter/src/rendering/binding.dart 405:18                                     drawFrame
    package:flutter/src/widgets/binding.dart 797:13                                       drawFrame
    package:flutter/src/rendering/binding.dart 283:5                                      [_handlePersistentFrameCallback]
    package:flutter/src/scheduler/binding.dart 1109:15                                    [_invokeFrameCallback]
    package:flutter/src/scheduler/binding.dart 1048:9                                     handleDrawFrame
    package:flutter/src/scheduler/binding.dart 857:7                                      <fn>
    package:dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 50:19       internalCallback
    ════════════════════════════════════════════════════════════════════════════════════════════════════
    Another exception was thrown: NoSuchMethodError: invalid member on null: 'doesFitBounds'
    Another exception was thrown: Assertion failed: org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/surface/scene_builder.dart:267:12
    Another exception was thrown: Assertion failed: org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/surface/scene_builder.dart:267:12
    Another exception was thrown: Assertion failed: org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/surface/scene_builder.dart:267:12
    Another exception was thrown: Assertion failed: org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/surface/scene_builder.dart:267:12
    

    my flutter doctor:

    Doctor summary (to see all details, run flutter doctor -v):
    [✓] Flutter (Channel beta, v1.14.6, on Mac OS X 10.15.3 19D76, locale es-419)
    [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    [✓] Xcode - develop for iOS and macOS (Xcode 11.3.1)
    [✓] Chrome - develop for the web
    [✓] Android Studio (version 3.5)
    [✓] VS Code (version 1.43.0)
    [✓] Connected device (2 available)
    
    • No issues found!
    
    opened by danieramiz 6
  • Method `onChange` is called when widget initializes

    Method `onChange` is called when widget initializes

    I'm using SleekCircularSlider in a StreamBuilder to show the audio player's progress. Also, users could use the slider to seek the player. The problem is that method onChange is called even when the user is not selecting the slider. Here is my code:

      Widget positionIndicator(MediaItem mediaItem, PlaybackState state,
          AudioProcessingState processingState) {
        if (processingState == AudioProcessingState.none) {
          return SleekCircularSlider(
              appearance: CircularSliderAppearance(
                  spinnerMode: true,
                  size: 225,
                  customWidths: CustomSliderWidths(trackWidth: 4, progressBarWidth: 13)));
        }
        double seekPos;
        return StreamBuilder(
          stream: Rx.combineLatest2<double, double, double>(
              _dragPositionSubject.stream,
              Stream.periodic(Duration(milliseconds: 200)),
                  (dragPosition, _) => dragPosition),
          builder: (context, snapshot) {
            double position =
                snapshot.data ?? state.currentPosition.inMilliseconds.toDouble();
            double duration = mediaItem?.duration?.inMilliseconds?.toDouble();
            print("positionIndicator $position/$duration ${state.processingState}");
            return Column(
              children: [
                if (duration != null &&
                    !(position == 0 && state.processingState != AudioProcessingState.ready))
                  SleekCircularSlider(
                    appearance: CircularSliderAppearance(
                        size: 225,
                        startAngle: 270,
                        angleRange: 360,
                        customWidths:
                        CustomSliderWidths(trackWidth: 4, progressBarWidth: 13)),
                    min: 0.0,
                    max: duration,
                    initialValue: seekPos ?? max(0.0, min(position, duration)),
                    innerWidget: (double percentage) => Text(''),
                    onChange: (double value) {
                      print('on change');
                      _dragPositionSubject.add(value);
                    },
                    onChangeEnd: (value) {
                      print('on change end');
                      AudioService.seekTo(Duration(milliseconds: value.toInt()));
                      seekPos = value;
                      _dragPositionSubject.add(null);
                    },
                  ),
                if (duration == null ||
                    (position == 0 && state.processingState != AudioProcessingState.ready))
                  SleekCircularSlider(
                      appearance: CircularSliderAppearance(
                          spinnerMode: true,
                          size: 225,
                          customWidths:
                          CustomSliderWidths(trackWidth: 4, progressBarWidth: 13))),
              ],
            );
          },
        );
      }
    
    opened by zjamshidi 4
  • Circular gradient - show full gradient

    Circular gradient - show full gradient

    How can I make the gradient be the full color spectrum even if the progress is only partial? For instance, if the progress is only 0.2, I actually want to see the whole sweep from blue to red. Not just the blue part

    Another flutter widget has this same issue: https://github.com/diegoveloper/flutter_percent_indicator/issues/31

    any clue how to solve this?

    opened by MobileMon 3
  • circular_slider requires SDK version >=2.12.0 <3.0.0, version solving failed.

    circular_slider requires SDK version >=2.12.0 <3.0.0, version solving failed.

    Hi when I add the dependance in the YAML file and make a "flutter pub get" I always have this message

    The current Dart SDK version is 2.9.1.
    
    Because circular_slider requires SDK version >=2.12.0 <3.0.0, version solving failed.
    Running "flutter pub get" in circular_slider...
    pub get failed (1; Because circular_slider requires SDK version >=2.12.0 <3.0.0, version solving failed.)
    
    

    here is my YAML file :

    name: circular_slider
    description: A new Flutter project.
    
    
    publish_to: 'none' # Remove this line if you wish to publish to pub.dev
    
    version: 1.0.0+1
    
    environment:
      sdk: ">=2.12.0 <3.0.0"
    
    dependencies:
      flutter:
        sdk: flutter
      sleek_circular_slider:
        path: ../
      cupertino_icons: ^0.1.3
    
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
    
    flutter:
      uses-material-design: true
    
     
    

    Can anyone help me please ?

    opened by sbois 2
  • Max value cant be more than initalValue

    Max value cant be more than initalValue

    For my purpose, I am trying to track time spent doing an activity. The max value of the ring is the total time the activity should take, but the user can take more than this time. I am setting initial value to the time user is taking, so that when the user has gone over the total time the activity should take (max value) I was expected the ring to start filling a second time, going over the max as shown in the mock up below. What can I change to make this possible?

    Screen Shot 2021-08-16 at 9 53 43 AM
    opened by mariapapag95 2
  • prevent animation if angle not changed

    prevent animation if angle not changed

    Hi @matthewfx Thanks for package.

    I'm writing a wrapper reactive_sleek_circular_slider for reactive_forms package. Basically I'm supporting this form engine by writing as much prebuilt wrappers as possible.

    Currently I have an issue when using it with forms.

    I swipe to change then I update initialValue to be in sync with form and to allow to change values programmaticaly. In this case slider animates despite current and upcoming angles are the same.

    opened by vasilich6107 2
  • After setting initial value ,min and max dynamically the slider doesnt reset to intitial value .

    After setting initial value ,min and max dynamically the slider doesnt reset to intitial value .

    After setting initial value ,min and max dynamically the slider doesnt reset to intitial value .It show same position of slider ,though min, max change are working

    opened by Aashutosh3804 2
  • Disabling Sliding Property

    Disabling Sliding Property

    I have used a button widget inside SleekCircularSlider() but when button is disabled, I want to disable the slide property of the slider and vice versa . In other words, I want to do enable/ disable slider based on a boolean value.

    I was wondering if is there any way to make this thing possible as I was unable to find any parameter that would be helpful in my case.

    opened by Chetan-Goyal 2
  • Error when initial value equals to min value

    Error when initial value equals to min value

    Problem!

    This may seems strange but it actually gives an error when I set the initial value equals to the same min value. I currently solved it by increase the initial value by 2. Here's my code.

    @override
    Widget build(BuildContext context) {
      return SleekCircularSlider(
        initialValue: widget.value <= widget.min ? widget.value + 2 : widget.value,
        innerWidget: _buildInnerWidget,
        appearance: CircularSliderAppearance(
          size: 200,
          customWidths: CustomSliderWidths(
            trackWidth: 2,
            progressBarWidth: 10,
          ),
          customColors: CustomSliderColors(
            progressBarColors: [
              const Color(0xffe74c3c),
              const Color(0xffe67e22),
              const Color(0xfff1c40f),
            ],
            trackColor: Colors.white12,
            shadowColor: const Color(0xffe74c3c),
          ),
          animationEnabled: true,
        ),
        min: widget.min,
        max: widget.max,
        onChange: (val) => setState(() => currentValue = val),
        onChangeEnd: (val) => widget.onChaged(val),
      );
    }
    

    Error!

    The error was in the framework since multiple things went wrong too inside the framework..

    The following assertion was thrown building Expanded(flex: 1): 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4224 pos 12: '!_dirty': is not true.

    Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause. In either case, please report this assertion by filing a bug on GitHub: https://github.com/flutter/flutter/issues/new?template=BUG.md

    Hope you can fix it as soon as possible. Thanks.

    opened by devmuaz 2
  • Has this been abandoned? Anyone have a replacement? 🤔

    Has this been abandoned? Anyone have a replacement? 🤔

    This repo hasn't had an update in quite a while--which is a shame because this is one of the nicest widgets I've found. 💯

    Has anyone found or created an alternative that's getting updates?

    Several of the open issues on this are features I'd love to see. I'm a little too new to Flutter to contribute myself. 😅

    opened by cliftonlabrum 1
  • Creating a Proper Semi Circular Slider Widget in Flutter (PAID)

    Creating a Proper Semi Circular Slider Widget in Flutter (PAID)

    how do we create a proper Semi Circular Slider that has "steps" line division. I have checked out many packages on pub.dev but they doesn't seem to provide a proper Semi Circular Slider. They look more like progress bar rather than a slider

    Is it possible for anyone to code this quickly for a couple of bucks?

    image

    opened by Jayvd 0
Owner
Mat Nuckowski
Mat Nuckowski
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
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
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
A Flutter widget to use Apache ECharts (incubating) in a reactive way.

中文 [![pub](https://img.shields.io/pub/v/flutter_echarts.svg)](https://pub.dev/packages/flutter_echarts) A Flutter widget to use Apache ECharts in a re

LIN Chen 629 Dec 29, 2022
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
Flutter cryptocurrency UI dashboard.

?? ?? Crypto Dashboard Flutter UI Kit ?? ?? ?? ⭐️ ⭐️ ??‍?? Free Flutter UI Kits based on designs on UpLabs ?? . Watch Youtube Speed code Tutorial Here

Olayemii Garuba 69 Nov 20, 2022
A scrollable time chart in Flutter.

time_chart An amazing time chart in Flutter. Chart Types TimeChart AmountChart Getting Started 1 - Depend on it Add it to your package's pubspec.yaml

Minseong Kim 26 Oct 28, 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
A library to draw fantastic bar charts race in Flutter

bar_chart_race The first library to draw fantastic bar charts race in Flutter Usage Let's get started add the dependencies to your app: dependencies:

Mimene Younes 6 Jun 24, 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
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
MPAndroidChart Flutter version

MPFlutterChart flutter charts just like MPAndroidChart The minimum version currently supported is 1.7.3. If you use flutter with lower version, checko

null 287 Dec 21, 2022
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 flutter package which makes it easier to plot different types of charts with lots of customization, made purely in dart

multi_charts It is a library that provides different types of charts to plot data points. Currently it supports only Radar Chart, but will support mor

Intkhab Ahmed 28 Nov 9, 2022
Flutter package for creating simple yet modern looking charts

A package for creating simple yet modern looking charts. Five chart types Bar Gauge Line Pie Radar Canvas + DOM modern_charts combines Canvas and DOM

Man Hoang 68 Nov 4, 2022
Animated line chart for flutter

fl_animated_linechart An animated chart library for flutter. Support for datetime axis Multiple y axis, supporting different units Highlight selection

null 51 Sep 25, 2022
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.

GraphView Get it from | Flutter GraphView is used to display data in graph structures. It can display Tree layout, Directed and Layered graph. Useful

Nabil Mosharraf 326 Jan 6, 2023