GithubHelp home page GithubHelp logo

matthewfx / sleek_circular_slider Goto Github PK

View Code? Open in Web Editor NEW
516.0 6.0 99.0 5.12 MB

Sleek circular slider for Flutter

License: MIT License

Dart 97.29% Kotlin 0.59% Swift 0.71% Objective-C 0.07% Ruby 1.34%
flutter flutter-package slider circular-progress dart customizable ios android

sleek_circular_slider's Introduction

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!

sleek_circular_slider's People

Contributors

kkujawinski avatar martin-dimi avatar matthewfx avatar nero-angela avatar vasilich6107 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

sleek_circular_slider's Issues

progressBarColors start with wrong color

Hi there,

Im working with the package as a progressbar.
I use 3 colors inside: progressBarColors
But it looks like the color is repeating itself? Im starting with a green color, then a yellow and then a red.
But at the beginning Im seeing a small yellow color and then the green, then yellow again.

Is there any possibility to fix this?

Max limit issue

Thanks for the amazing widget. I found when I set the max to 2000, the actual limit will be 2001. The print value from onChange is "I/flutter (29316): 2000.0000000000002". I am not sure if I am doing something wrong or this is a bug. Thanks

Updated: weird... the actual max limit will be affected by the min value. If I set min:6 max:2000 then the actual max will be 2001. set min other than 6 will be fine.

Cant start gradient from 270

Hey, cool package!

I start my slider from startAngle: 270 and angleRange: 360. So it spins around like a clock.

I then want to apply a gradient of three colors progressing from red to yellow to green.

But I can't start gradient from gradientStartAngle: 270, because it doesn't work if I set the gradientEndAngle to 630 (270+360) or any other solutions I could think of.

Did I simply misunderstood? Couldn't google any solutions.

I have done a temporary fix by setting it gradientStart: 0 and end: 360 and then settings colors as yellow, green, red, but it doesn't seem like a great fix :-)

Add track gradient

It would be great if you could add a gradient for the track!
Either use the progressBarColors when trackColor is null.
Or something like this in _CurvePainter by adding trackColors:

  final progressBarRect = Rect.fromLTWH(0.0, 0.0, size.width, size.width);

  Paint trackPaint;
  if (appearance.trackColors != null){
    final trackGradient = SweepGradient(
      startAngle: degreeToRadians(appearance.gradientStartAngle),
      endAngle: degreeToRadians(appearance.gradientStopAngle),
      tileMode: TileMode.mirror,
      colors: appearance.trackColors,
    );
    trackPaint = Paint()
      ..shader = trackGradient.createShader(progressBarRect)
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = appearance.trackWidth;
  } else {
    trackPaint = Paint()
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = appearance.trackWidth
      ..color = appearance.trackColor;
  }
  drawCircularArc(
      canvas: canvas,
      size: size,
      paint: trackPaint,
      ignoreAngle: true,
      spinnerMode: appearance.spinnerMode);

offset is NaN

found a bug when min equals max the method of
double valueToPercentage(double value, double min, double max) { return value / ((max - min) / 100); }
in utils.dart return NaN because of division by zero.

as a workaround, I'm checking when min==max and setting max=min+0.1

Add Gauge Chart?

Could you please add a gauge visualization chart to this library? Awesome package btw.

Ability to show innerWidget in spinnerMode.

Awesome widget!

innerWidget not shown in spinnerMode by default, is there any possible to show innerWidget when spinnerMode set true, cause I want to show some tips inside where use as spinner.

Thanks in advance.

Tap handlers and scroll issue

It would be extremely useful to have a possibility to disable handling taps on Track. So the user will be able to change slider position only by dragging the Dot.

The use case:
I have several sliders inside a ListView and it is impossible to scroll ListView tapping anywhere around the slider.

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.

Edit: my mistake

EDIT: I was experimenting with it in a wrong way, it indeed responds to external changes of state.

Linked Sliders

Sry, i found the answer to my simple problem, and if you see this message is that i didn't find how to delete it :).

Thanks for this amazing package anyways !

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!

Request: Animation Duration

Functionality request: Animation Duration parameter when using the slider as a static progress bar instead of a slider.

When I say animation duration, I mean being able to set the duration it takes for the progress bar to go from zero to the value set.

Side note: This is the best slider package out there for Flutter, and an enormous kudos to the authors!!

assertion: line 45 pos 16: 'min <= max': is not true.

The following assertion was thrown building PlayOutPlayer(dirty, dependencies: [MediaQuery], state: _PlayOutPlayer#f3517):
'package:sleek_circular_slider/src/circular_slider.dart': Failed assertion: line 45 pos 16: 'min <= max': is not true.

set currently value of slider

in my case I have a music player and I need the currently value of slider , update based on the music position .
I want value parameter like default flutter slider.

Make the handle a Widget rather than always a circle.

This feature will open a lot more customizability to the seek bar handle as it is not constrained to a circle where we can only set the color. Also other features that are internally implemented (labels, track shape border) may maybe also be lifted as a Widget so we can customize it.

ReadOnly mode [enhancement]

Awsome Widget pal!
Just a suggestion, easy to implement. I miss a readonly property and saw it is just a few lines change.

  1. Add a property readOnly to class
  2. _interactionEnabled is the point! I've added && !widget.readOnly to line:

bool get _interactionEnabled => !widget.readOnly && (widget.onChangeEnd != null || widget.onChange != null && !widget.appearance.spinnerMode);

It would be great!
Thanks in advance

MainTrack steps

Hi there!

Amazing work on the lib!
I would love to see the option to have the slider move in steps rather than continuously. For instance, if the user is only allowed to select values multiple of 5 (5, 10, 15..). We can set the main label to only display such values
((v / 5).round() * 5).toString()
however, there's no way of making the slider itself skip/jump in increments of 5.

how to change slider value without user interaction

Hello
I was searching for a circle slider and i found yours , thanks for it ^^
so i'm using it for playing an audio , and i need to change it's value depends on my audio position, is there any way to handle this ?

(Initial) Value greater than Max Value

First of all, great work on this lib! I love how beautiful and customizable it is!

I ran into a scenario where the initialvalue field was updated with a value greater than the max.
Imagine if someone set a number of calories, but managed to pass that number. It would be nice if we could represent that, maybe with a separated slider color as well to represent that the max value was overpassed.

Keep up the great work!

Detect if value change come from user

Thanks for this widget,it is really awesome and customizable, but i am wondering if i want to set a value dynamically how would i do it? well, i can set the initial value and i can update it, but if i want to use both user interaction change and dynamic value change i can't do it, if you can add where i can know if the value change is coming from the user interaction or not, it could be useful in many cases.

Add more features

Hi dear
thank you for helping us by introducing this amazing slider.
Actually I don't have issue but I ask you to add more features like make it work as a progress indicator.
Thank you

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.

Changing the appearance does not update the UI

Changing the UI either via animation or changing the appearance values (and calling setState) does not rebuild the widget. This causes the slider appearance to be static on creation but unable to update.

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);
            },
          )

Request: Option to select / remove stroke cap for progress bar

The stroke cap of the progress bar paint is hardcoded as round. As a result, it doesn't show the exact value, but adds extra as seen in the image below. The value is 50% but the cap makes it look more. I would like to have an option to remove the cap.

image

    final progressBarPaint = Paint()
      ..shader = progressBarGradient.createShader(progressBarRect)
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = appearance.progressBarWidth;

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.

Can I change the dot to an icon?

Hi, this is a great package. Thanks for making it!

I see that you can change the dot color, but I would like to change it from a dot to an icon. How should I do that?

Screen Shot 2021-08-12 at 1 33 01 PM

Screen Shot 2021-08-12 at 1 32 13 PM

dynamic spinnerMode causes errors

I'm trying to dynamically change it from a spinner to an initalValue. When I change the spinnerMode property from an outside widget I see this:

_SleekCircularSliderState is a SingleTickerProviderStateMixin but multiple tickers were created.

It would be great to be able to change that on the fly.

Max = min causes an unhandled exception

If max value equals min value, an unhandled exception is thrown by this code because it attempts to divide by zero:

  final divider = (max - min) / 100;
  return (value - previous).abs() ~/ divider * 15;

Slider Markers

Can we add markers around the slider, for eg. creating a clock so can we have markings around the circle denoting 12,3,6 & 9 ?

I got this exception ?

I don't what action leads to this :

The following _CastError was thrown while dispatching a pointer event:
Null check operator used on a null value

When the exception was thrown, this was the stack: 
#0      _SleekCircularSliderState._onPanDown (package:sleek_circular_slider/src/circular_slider.dart:285:58)
#1      _CustomPanGestureRecognizer.addPointer (package:sleek_circular_slider/src/custom_gesture_recognizer.dart:16:18)
#2      RawGestureDetectorState._handlePointerDown (package:flutter/src/widgets/gesture_detector.dart:1205:18)
#3      RenderPointerListener.handleEvent (package:flutter/src/rendering/proxy_box.dart:2829:29)
#4      GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:419:22)
...
Event: PointerDownEvent#4ef6d(position: Offset(233.0, 349.6))
  position: Offset(233.0, 349.6)
Target: RenderPointerListener#a3f84 relayoutBoundary=up9
  parentData: <none> (can use size)
  constraints: BoxConstraints(unconstrained)
  size: Size(150.0, 150.0)
  behavior: deferToChild
  listeners: down
====================================================================================================

can't get callback value with onChange method

I can't get any callback value with on** method

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

void main() => runApp(const MyApp());

/// This is the main application widget.
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  String percentageModifier(double value) {
    final roundedValue = value.ceil().toInt().toString();
    return '$roundedValue %';
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                child: SleekCircularSlider(
                  appearance: CircularSliderAppearance(
                      spinnerDuration: 2000,
                      spinnerMode: false,
                      startAngle: 270,
                      angleRange: 360,
                      customColors:
                          CustomSliderColors(progressBarColor: Colors.red),
                      customWidths: CustomSliderWidths(progressBarWidth: 10),
                      infoProperties:
                          InfoProperties(modifier: percentageModifier)),
                  min: 0,
                  max: 100,
                  initialValue: 45,
                  onChange: (double value) {
                    print('onChange...');
                    print('value: $value');
                  },
                  onChangeStart: (double startValue) {
                    print('onChangeStart...');
                    print('startValue: $startValue');
                  },
                  onChangeEnd: (double endValue) {
                    print('onChangeEnd...');
                    print('endValue: $endValue');
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Ability to change circle handler apearance

Hi,
It would be a very great enhancement if we could customize the handler appearance too(for example drawing a triangle instead of a circle), is it possible for you to implement such a feature?

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))),
          ],
        );
      },
    );
  }

Widget max attribute only takes in static double

I have a CircularSlider that has max values that are not static, as they are dependant on what the user sets the value to be. This caused an exception:

EXCEPTION CAUGHT BY WIDGETS LIBRARY
The following UnsupportedError was thrown building SliderLabel(dirty):
I/flutter ( 5516): Unsupported operation: Infinity or NaN toInt

Screenshot 2020-07-17 at 2 29 19 AM

Request: Sliding direction preference

The sliding direction is only clock-wise direction as far as I understand. It would be great to add a property implying the sliding direction, it can be either clock-wise direction or counter clockwise direction.

Custom handle

Is there a way to make custom handler, like icon widget or canvas?

Progress Bar Colour doesn't change on state Change

SleekCircularSlider seems to be a StatefulWidget so when changing the state of the progress bar colour it just keeps it's initial colour. What would be the best way to update the progress bar colour without rebuilding the page?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.