https://medium.com/flutter-community/flutter-sliders-demystified-4b3ea65879c
https://gist.github.com/AnkitChowdhury
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
// Application name
title: 'Flutter Stateful Clicker Counter',
theme: ThemeData(
// Application theme data, you can set the colors for the application as
// you want
primarySwatch: Colors.blue,
),
home: SliderWidget(),
);
}
}
class SliderWidget extends StatefulWidget {
final double sliderHeight;
final int min;
final int max;
final fullWidth;
SliderWidget({this.sliderHeight = 48, this.max = 10, this.min = 0, this.fullWidth = false});
@override
_SliderWidgetState createState() => _SliderWidgetState();
}
class _SliderWidgetState extends State<SliderWidget> {
double _value = 0;
@override
Widget build(BuildContext context) {
double paddingFactor = .2;
if (this.widget.fullWidth) paddingFactor = .3;
return Scaffold(
body: Center(
child: Container(
width: this.widget.fullWidth ? double.infinity : (this.widget.sliderHeight) * 5.5,
height: (this.widget.sliderHeight),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(
Radius.circular((this.widget.sliderHeight * .3)),
),
gradient: new LinearGradient(
colors: [
const Color(0xFF00c6ff),
const Color(0xFF0072ff),
],
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 1.00),
stops: [
0.0,
1.0
],
tileMode: TileMode.clamp),
),
child: Padding(
padding: EdgeInsets.fromLTRB(this.widget.sliderHeight * paddingFactor, 2, this.widget.sliderHeight * paddingFactor, 2),
child: Row(
children: <Widget>[
Text(
'${this.widget.min}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: this.widget.sliderHeight * .3,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
SizedBox(
width: this.widget.sliderHeight * .1,
),
Expanded(
child: Center(
child: SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor: Colors.white.withOpacity(1),
inactiveTrackColor: Colors.white.withOpacity(.5),
trackHeight: 4.0,
thumbShape: CustomSliderThumbCircle(
thumbRadius: this.widget.sliderHeight * .4,
min: this.widget.min,
max: this.widget.max,
),
overlayColor: Colors.white.withOpacity(.4),
activeTickMarkColor: Colors.white,
inactiveTickMarkColor: Colors.red.withOpacity(.7),
),
child: Slider(
value: _value,
onChanged: (value) {
setState(() {
_value = value;
});
}),
),
),
),
SizedBox(
width: this.widget.sliderHeight * .1,
),
Text(
'${this.widget.max}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: this.widget.sliderHeight * .3,
fontWeight: FontWeight.w700,
color: Colors.white,
),
),
],
),
),
),
),
);
}
}
class CustomSliderThumbRect extends SliderComponentShape {
final double thumbRadius;
final thumbHeight;
final int min;
final int max;
const CustomSliderThumbRect({
this.thumbRadius,
this.thumbHeight,
this.min,
this.max,
});
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return Size.fromRadius(thumbRadius);
}
@override
void paint(
PaintingContext context,
Offset center, {
Animation<double> activationAnimation,
Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme,
TextDirection textDirection,
double value,
double textScaleFactor,
Size sizeWithOverflow,
}) {
final Canvas canvas = context.canvas;
final rRect = RRect.fromRectAndRadius(
Rect.fromCenter(center: center, width: thumbHeight * 1.2, height: thumbHeight * .6),
Radius.circular(thumbRadius * .4),
);
final paint = Paint()
..color = sliderTheme.activeTrackColor //Thumb Background Color
..style = PaintingStyle.fill;
TextSpan span = new TextSpan(style: new TextStyle(fontSize: thumbHeight * .3, fontWeight: FontWeight.w700, color: sliderTheme.thumbColor, height: 1), text: '${getValue(value)}');
TextPainter tp = new TextPainter(text: span, textAlign: TextAlign.left, textDirection: TextDirection.ltr);
tp.layout();
Offset textCenter = Offset(center.dx - (tp.width / 2), center.dy - (tp.height / 2));
canvas.drawRRect(rRect, paint);
tp.paint(canvas, textCenter);
}
String getValue(double value) {
return (min + (max - min) * value).round().toString();
}
}
class CustomSliderThumbCircle extends SliderComponentShape {
final double thumbRadius;
final int min;
final int max;
const CustomSliderThumbCircle({
@required this.thumbRadius,
this.min = 0,
this.max = 10,
});
@override
Size getPreferredSize(bool isEnabled, bool isDiscrete) {
return Size.fromRadius(thumbRadius);
}
@override
void paint(
PaintingContext context,
Offset center, {
Animation<double> activationAnimation,
Animation<double> enableAnimation,
bool isDiscrete,
TextPainter labelPainter,
RenderBox parentBox,
SliderThemeData sliderTheme,
TextDirection textDirection,
double value,
double textScaleFactor,
Size sizeWithOverflow,
}) {
final Canvas canvas = context.canvas;
final paint = Paint()
..color = Colors.white //Thumb Background Color
..style = PaintingStyle.fill;
TextSpan span = new TextSpan(
style: new TextStyle(
fontSize: thumbRadius * .8,
fontWeight: FontWeight.w700,
color: sliderTheme.thumbColor, //Text Color of Value on Thumb
),
text: getValue(value),
);
TextPainter tp = new TextPainter(text: span, textAlign: TextAlign.center, textDirection: TextDirection.ltr);
tp.layout();
Offset textCenter = Offset(center.dx - (tp.width / 2), center.dy - (tp.height / 2));
canvas.drawCircle(center, thumbRadius * .9, paint);
tp.paint(canvas, textCenter);
}
String getValue(double value) {
return (min + (max - min) * value).round().toString();
}
}

0 Comments