Sleek circular slider/progress bar & spinner 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
  • 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 2
  • 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
  • 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
A fluid design slider that works just like the Slider material widget.

Fluid Slider for Flutter Inspired by a dribbble by Virgil Pana. A fluid design slider that works just like the Slider material widget. Used to select

Vamsi Krishna 311 Dec 30, 2022
RangeSlider Widget for Flutter

RangeSlider An extension of the Flutter Material Slider to allow selection of a range of values via 2 thumbs. Step by step explanation A full explanat

Didier Boelens 360 Dec 30, 2022
Sleek circular slider for Flutter

Sleek circular slider/progress bar & spinner for Flutter A highly customizable circular slider/progress bar & spinner for Flutter. Getting Started Ins

Mat Nuckowski 476 Dec 16, 2022
Flutter fluid slider - A fluid design slider that works just like the Slider material widget

Fluid Slider for Flutter Inspired by a dribbble by Virgil Pana. A fluid design s

Jay Raj 2 Feb 18, 2022
MindInventory 15 Sep 5, 2022
Open source Flutter package, simple circular progress bar.

Simple circular progress bar Open source Flutter package, simple circular progress bar. Getting Started Installing Basic Examples Colors Start angle L

null 6 Dec 23, 2022
A customizable circular slider for Flutter.

flutter_circular_slider A customizable circular slider for Flutter. Getting Started Installation Basic Usage Constructor Use Cases Installation Add fl

David 193 Nov 14, 2022
A Flutter widget to set time with spinner instead of material time picker

flutter_time_picker_spinner Time Picker widget with spinner instead of a material time picker. 12H format 24H format 24H format with second Custom sty

Bobby Stenly Irawan 34 Aug 8, 2022
A simple button that gives you the possibility to transform into a circular one and shows a progress indicator

Progress Button A simple button that gives you the possibility to transform into

Daniel B Schneider 0 Dec 22, 2021
Circular Bottom Navigation Iman KhoshabiCircular Bottom Navigation [368⭐] - Beautiful animated bottom navigation bar by Iman Khoshabi.

Circular Bottom Navigation (or maybe a tab bar). This is implementation of an artwork in Uplabs Donate Support us by becoming a patron on Patreon Let'

Iman khoshabi 523 Dec 30, 2022
A material design slider and range slider with rtl support and lots of options and customization for flutter

flutter_xlider (Flutter Slider) A material design slider and range slider, horizontal and vertical, with rtl support and lots of options and customiza

null 407 Jan 6, 2023
A flutter widget for comparing two stacked widgets by dragging a slider thumb to reveal either sides of the slider horizontally or vertically.

Juxtapose A flutter widget for comparing two stacked widgets by dragging a slider thumb to reveal either sides of the slider horizontally or verticall

Leslie Arkorful 74 Nov 24, 2022
Flutter custom carousel slider - A carousel slider widget,support custom decoration suitable for news and blog

flutter_custom_carousel_slider A carousel slider Flutter widget, supports custom

Emre 40 Dec 29, 2022
A fluid design slider that works just like the Slider material widget.

Fluid Slider for Flutter Inspired by a dribbble by Virgil Pana. A fluid design slider that works just like the Slider material widget. Used to select

Vamsi Krishna 311 Dec 30, 2022
A simple modal progress HUD (heads-up display, or progress indicator) for flutter

modal_progress_hud A simple widget wrapper to enable modal progress HUD (a modal progress indicator, HUD = Heads Up Display) Inspired by this article.

Maurice McCabe 157 Nov 22, 2022
Flutter package to diplay progress through a milestone progress widget

milestone_progress Flutter package for IOS and Android to display progress through milestone progress widget. Screenshots ## Usage [Example]https://gi

Harpreet Singh 16 Aug 4, 2020
Progress State Button - A customizable progress button for Flutter

Progress State Button - A customizable progress button for Flutter

Selim 108 Dec 12, 2022
Wave progress - A custom wave progress widget

wave_progress_widget A customable wave progress widget Preview How to use Add this to your package's pubspec.yaml file: dependencies: wave_progress_

idan ben shimon 41 Jul 18, 2022
Flutter File Select and Upload to the Server with Progress Bar - Day 44

Flutter File Select and Upload - Day 44 class Afgprogrammer extends Flutter100DaysOfCode { video() { return { "title": "Flutter File Selec

Mohammad Rahmani 30 Dec 17, 2022
A Simple and easy to use flutter package for showing progress bar.

progress_dialog A Simple and easy to use flutter package for showing progress bar. #Usage Import the package import 'package:custom_progress_dialog/cu

Vikas Jilla 6 May 23, 2022