├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── lib └── fluid_slider.dart ├── preview.gif ├── pubspec.lock ├── pubspec.yaml └── test └── fluid_slider_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .packages 28 | .pub-cache/ 29 | .pub/ 30 | build/ 31 | 32 | # Android related 33 | **/android/**/gradle-wrapper.jar 34 | **/android/.gradle 35 | **/android/captures/ 36 | **/android/gradlew 37 | **/android/gradlew.bat 38 | **/android/local.properties 39 | **/android/**/GeneratedPluginRegistrant.java 40 | 41 | # iOS/XCode related 42 | **/ios/**/*.mode1v3 43 | **/ios/**/*.mode2v3 44 | **/ios/**/*.moved-aside 45 | **/ios/**/*.pbxuser 46 | **/ios/**/*.perspectivev3 47 | **/ios/**/*sync/ 48 | **/ios/**/.sconsign.dblite 49 | **/ios/**/.tags* 50 | **/ios/**/.vagrant/ 51 | **/ios/**/DerivedData/ 52 | **/ios/**/Icon? 53 | **/ios/**/Pods/ 54 | **/ios/**/.symlinks/ 55 | **/ios/**/profile 56 | **/ios/**/xcuserdata 57 | **/ios/.generated/ 58 | **/ios/Flutter/App.framework 59 | **/ios/Flutter/Flutter.framework 60 | **/ios/Flutter/Generated.xcconfig 61 | **/ios/Flutter/app.flx 62 | **/ios/Flutter/app.zip 63 | **/ios/Flutter/flutter_assets/ 64 | **/ios/Flutter/flutter_export_environment.sh 65 | **/ios/ServiceDefinitions.json 66 | **/ios/Runner/GeneratedPluginRegistrant.* 67 | 68 | # Exceptions to above rules. 69 | !**/ios/**/default.mode1v3 70 | !**/ios/**/default.mode2v3 71 | !**/ios/**/default.pbxuser 72 | !**/ios/**/default.perspectivev3 73 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 74 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 677c4d5bb41681c707eebe9003429d93ed3d9695 8 | channel: master 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.0] - TODO: Add release date. 2 | 3 | * Added Basic Version of Slider 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | TODO: Add your license here. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flutter - Fluid Slider 2 | 3 | ### If this project has helped you out, please support us with a star. :star2: 4 | 5 | ## Preview 6 | ![Alt Text](preview.gif) 7 | 8 | ## Getting Started 9 | 10 | ```yamlgit 11 | dependencies: 12 | ... 13 | fluid_slider: 1.0.0 14 | ``` 15 | 16 | ## Usage Example 17 | 18 | Adding the widget 19 | 20 | ```dart 21 | import 'package:fluid_slider/fluid_slider.dart'; 22 | 23 | FluidSlider( 24 | min: 0, 25 | max: 100, 26 | sliderColor: Colors.indigo, 27 | textColor: Colors.white, 28 | onValue: (value) => {}, 29 | onSlide: (value) => {}, 30 | ) 31 | ``` 32 | 33 | ## Slider Properties 34 | 35 | | Property | Type | Required | Default Value | 36 | | ------------------- | ------------- | -------- | ------------- | 37 | | min | int | Yes | -- | 38 | | max | int | Yes | -- | 39 | | sliderColor | Color | No | Colors.indigo | 40 | | textColor | Color | No | Colors.indigo | 41 | | onValue | Function | Yes | -- | 42 | | onSlide | Function | No | -- | 43 | -------------------------------------------------------------------------------- /lib/fluid_slider.dart: -------------------------------------------------------------------------------- 1 | library fluid_slider; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class FluidSlider extends StatefulWidget { 6 | final min; 7 | final max; 8 | final onValue; 9 | final onSlide; 10 | final Color sliderColor; 11 | final Color textColor; 12 | 13 | FluidSlider( 14 | {Key key, 15 | @required this.min, 16 | @required this.max, 17 | @required this.onValue, 18 | this.onSlide, 19 | this.textColor, 20 | this.sliderColor}) 21 | : super(key: key); 22 | 23 | @override 24 | State createState() => FluidSliderState(this.textColor, this.min); 25 | } 26 | 27 | class FluidSliderState extends State { 28 | double indicatorBottom = 3; 29 | double indicatorLeft = 0; 30 | double sliderBarWidth = 0; 31 | bool isBubbleActive = false; 32 | int sliderValue = 0; 33 | int min = 0; 34 | TextStyle textStyle; 35 | final Color textColor; 36 | 37 | FluidSliderState(this.textColor, this.min) { 38 | textStyle = TextStyle(color: textColor ?? Colors.white, fontWeight: FontWeight.bold, fontSize: 13); 39 | sliderValue = (0 + min); 40 | } 41 | 42 | @override 43 | void initState() { 44 | super.initState(); 45 | // To set initial position -> indicatorLeft = ((widget.value / widget.max) * (sliderBarWidth - 30)); 46 | } 47 | 48 | void onLayoutUpdate(maxWidth) {} 49 | 50 | void onPanStart(DragStartDetails details) { 51 | setState(() { 52 | indicatorBottom = 35; 53 | isBubbleActive = true; 54 | }); 55 | } 56 | 57 | void onPanEnd(DragEndDetails details) { 58 | setState(() { 59 | indicatorBottom = 3; 60 | isBubbleActive = false; 61 | }); 62 | widget.onValue(sliderValue); 63 | } 64 | 65 | int getSliderValue(double position) { 66 | return (((indicatorLeft + position) / (sliderBarWidth - 36)) * (widget.max - widget.min)).roundToDouble().toInt(); 67 | } 68 | 69 | void onPanUpdate(DragUpdateDetails details) { 70 | double position = details.delta.dx; 71 | if (indicatorLeft + position > 0 && indicatorLeft + position < (sliderBarWidth - 36.0)) { 72 | if (widget.onSlide != null && getSliderValue(position) != sliderValue) { 73 | widget.onSlide(sliderValue); 74 | } 75 | setState(() { 76 | sliderValue = getSliderValue(position) + widget.min; 77 | indicatorLeft += position; 78 | }); 79 | } 80 | } 81 | 82 | Widget renderRangeIndicator(String rangeIndicatorValue) { 83 | return Padding( 84 | padding: EdgeInsets.all(8), 85 | child: Text(rangeIndicatorValue, style: textStyle), 86 | ); 87 | } 88 | 89 | Widget sliderBarLayout(context, BoxConstraints constraints) { 90 | sliderBarWidth = constraints.maxWidth; 91 | return Flex(direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ 92 | renderRangeIndicator(widget.min.toString()), 93 | renderRangeIndicator(widget.max.toString()), 94 | ]); 95 | } 96 | 97 | Widget sliderBar() { 98 | return AnimatedContainer( 99 | duration: Duration(microseconds: 300), 100 | decoration: BoxDecoration( 101 | borderRadius: BorderRadius.circular(6), 102 | color: widget.sliderColor ?? Colors.indigo, 103 | boxShadow: [ 104 | BoxShadow( 105 | color: Color.fromRGBO(188, 188, 188, 1), 106 | blurRadius: 5.0, // has the effect of softening the shadow 107 | spreadRadius: 0.5, // has the effect of extending the shadow 108 | offset: Offset(2, 2), 109 | ) 110 | ]), 111 | child: LayoutBuilder(builder: sliderBarLayout)); 112 | } 113 | 114 | Widget sliderIndicator() { 115 | return GestureDetector( 116 | onPanStart: onPanStart, 117 | onPanEnd: onPanEnd, 118 | onPanUpdate: onPanUpdate, 119 | child: AnimatedContainer( 120 | alignment: Alignment.center, 121 | duration: Duration(milliseconds: 250), 122 | height: 30, 123 | width: 30, 124 | decoration: BoxDecoration( 125 | shape: BoxShape.circle, 126 | border: Border.all(color: widget.sliderColor ?? Colors.indigo, width: 2), 127 | color: Colors.white, 128 | ), 129 | child: Center( 130 | child: (Text(sliderValue.toString(), style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold))))), 131 | ); 132 | } 133 | 134 | @override 135 | Widget build(BuildContext context) { 136 | return Container( 137 | height: 72, 138 | child: Flex(direction: Axis.vertical, mainAxisAlignment: MainAxisAlignment.end, children: [ 139 | Expanded( 140 | child: Stack(children: [ 141 | Positioned.fill( 142 | bottom: 0, 143 | child: Padding(padding: EdgeInsets.only(left: 5, right: 5, bottom: 0, top: 36), child: sliderBar())), 144 | AnimatedPositioned( 145 | duration: Duration(milliseconds: 50), 146 | bottom: indicatorBottom, 147 | left: indicatorLeft, 148 | child: Padding(padding: EdgeInsets.only(left: 8, right: 8), child: sliderIndicator())) 149 | ])) 150 | ])); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IronLad85/flutter-fluid-slider/004b0c6c5a2faae43cc943d3109da075bb849b5f/preview.gif -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: transitive 6 | description: 7 | name: archive 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.10" 11 | args: 12 | dependency: transitive 13 | description: 14 | name: args 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.5.2" 18 | async: 19 | dependency: transitive 20 | description: 21 | name: async 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.3.0" 25 | boolean_selector: 26 | dependency: transitive 27 | description: 28 | name: boolean_selector 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.0.5" 32 | charcode: 33 | dependency: transitive 34 | description: 35 | name: charcode 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.2" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.14.11" 46 | convert: 47 | dependency: transitive 48 | description: 49 | name: convert 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "2.1.1" 53 | crypto: 54 | dependency: transitive 55 | description: 56 | name: crypto 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.1.2" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | image: 71 | dependency: transitive 72 | description: 73 | name: image 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "2.1.4" 77 | matcher: 78 | dependency: transitive 79 | description: 80 | name: matcher 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "0.12.5" 84 | meta: 85 | dependency: transitive 86 | description: 87 | name: meta 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "1.1.7" 91 | path: 92 | dependency: transitive 93 | description: 94 | name: path 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "1.6.4" 98 | pedantic: 99 | dependency: transitive 100 | description: 101 | name: pedantic 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "1.8.0+1" 105 | petitparser: 106 | dependency: transitive 107 | description: 108 | name: petitparser 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "2.4.0" 112 | quiver: 113 | dependency: transitive 114 | description: 115 | name: quiver 116 | url: "https://pub.dartlang.org" 117 | source: hosted 118 | version: "2.0.5" 119 | sky_engine: 120 | dependency: transitive 121 | description: flutter 122 | source: sdk 123 | version: "0.0.99" 124 | source_span: 125 | dependency: transitive 126 | description: 127 | name: source_span 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.5.5" 131 | stack_trace: 132 | dependency: transitive 133 | description: 134 | name: stack_trace 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.9.3" 138 | stream_channel: 139 | dependency: transitive 140 | description: 141 | name: stream_channel 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "2.0.0" 145 | string_scanner: 146 | dependency: transitive 147 | description: 148 | name: string_scanner 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.0.5" 152 | term_glyph: 153 | dependency: transitive 154 | description: 155 | name: term_glyph 156 | url: "https://pub.dartlang.org" 157 | source: hosted 158 | version: "1.1.0" 159 | test_api: 160 | dependency: transitive 161 | description: 162 | name: test_api 163 | url: "https://pub.dartlang.org" 164 | source: hosted 165 | version: "0.2.5" 166 | typed_data: 167 | dependency: transitive 168 | description: 169 | name: typed_data 170 | url: "https://pub.dartlang.org" 171 | source: hosted 172 | version: "1.1.6" 173 | vector_math: 174 | dependency: transitive 175 | description: 176 | name: vector_math 177 | url: "https://pub.dartlang.org" 178 | source: hosted 179 | version: "2.0.8" 180 | xml: 181 | dependency: transitive 182 | description: 183 | name: xml 184 | url: "https://pub.dartlang.org" 185 | source: hosted 186 | version: "3.5.0" 187 | sdks: 188 | dart: ">=2.4.0 <3.0.0" 189 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: fluid_slider 2 | description: A Flutter UI for Fluid Slider inspired by native fluid slider of android. 3 | version: 1.0.0 4 | author: Siddharth V 5 | homepage: https://github.com/IronLad85/flutter-fluid-slider 6 | 7 | environment: 8 | sdk: ">=2.1.0 <3.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | 18 | # For information on the generic Dart part of this file, see the 19 | # following page: https://dart.dev/tools/pub/pubspec 20 | 21 | # The following section is specific to Flutter. 22 | flutter: 23 | 24 | # To add assets to your package, add an assets section, like this: 25 | # assets: 26 | # - images/a_dot_burr.jpeg 27 | # - images/a_dot_ham.jpeg 28 | # 29 | # For details regarding assets in packages, see 30 | # https://flutter.dev/assets-and-images/#from-packages 31 | # 32 | # An image asset can refer to one or more resolution-specific "variants", see 33 | # https://flutter.dev/assets-and-images/#resolution-aware. 34 | 35 | # To add custom fonts to your package, add a fonts section here, 36 | # in this "flutter" section. Each entry in this list should have a 37 | # "family" key with the font family name, and a "fonts" key with a 38 | # list giving the asset and other descriptors for the font. For 39 | # example: 40 | # fonts: 41 | # - family: Schyler 42 | # fonts: 43 | # - asset: fonts/Schyler-Regular.ttf 44 | # - asset: fonts/Schyler-Italic.ttf 45 | # style: italic 46 | # - family: Trajan Pro 47 | # fonts: 48 | # - asset: fonts/TrajanPro.ttf 49 | # - asset: fonts/TrajanPro_Bold.ttf 50 | # weight: 700 51 | # 52 | # For details regarding fonts in packages, see 53 | # https://flutter.dev/custom-fonts/#from-packages 54 | -------------------------------------------------------------------------------- /test/fluid_slider_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | test('Empty Test', () { 5 | 6 | }); 7 | } 8 | --------------------------------------------------------------------------------