Flutter slider with gradient
Solution 1
I've now created a custom track shape class based on this youtube video and added a gradient property into the constructor.
How to use it:
Gradient:
LinearGradient gradient = LinearGradient(
colors: <Color> [
Colors.red,
Colors.orange,
Colors.yellow,
Colors.green,
Colors.blue,
Colors.blue[900],
Colors.purple
]
);
Slider:
(The property darkenInactive = false is used to not darken the slider on the inactive side.)
SliderTheme(
data: SliderThemeData(
trackShape: GradientRectSliderTrackShape(gradient: gradient, darkenInactive: false),
),
child: Slider(
min: 0,
max: 10,
value: value,
onChanged: (double value) {},
)
),
Shape class:
import 'package:flutter/material.dart';
/// Based on https://www.youtube.com/watch?v=Wl4F5V6BoJw
class GradientRectSliderTrackShape extends SliderTrackShape
with BaseSliderTrackShape {
const GradientRectSliderTrackShape({
this.gradient = const LinearGradient(
colors: [
Colors.red,
Colors.yellow,
],
),
this.darkenInactive = true,
});
final LinearGradient gradient;
final bool darkenInactive;
@override
void paint(
PaintingContext context,
Offset offset,
{
required RenderBox parentBox,
required SliderThemeData sliderTheme,
required Animation<double> enableAnimation,
required TextDirection textDirection,
required Offset thumbCenter,
bool isDiscrete = false,
bool isEnabled = false,
double additionalActiveTrackHeight = 2,
}
) {
assert(sliderTheme.disabledActiveTrackColor != null);
assert(sliderTheme.disabledInactiveTrackColor != null);
assert(sliderTheme.activeTrackColor != null);
assert(sliderTheme.inactiveTrackColor != null);
assert(sliderTheme.thumbShape != null);
assert(sliderTheme.trackHeight != null && sliderTheme.trackHeight! > 0);
final Rect trackRect = getPreferredRect(
parentBox: parentBox,
offset: offset,
sliderTheme: sliderTheme,
isEnabled: isEnabled,
isDiscrete: isDiscrete,
);
final activeGradientRect = Rect.fromLTRB(
trackRect.left,
(textDirection == TextDirection.ltr)
? trackRect.top - (additionalActiveTrackHeight / 2)
: trackRect.top,
thumbCenter.dx,
(textDirection == TextDirection.ltr)
? trackRect.bottom + (additionalActiveTrackHeight / 2)
: trackRect.bottom,
);
// Assign the track segment paints, which are leading: active and
// trailing: inactive.
final ColorTween activeTrackColorTween = ColorTween(
begin: sliderTheme.disabledActiveTrackColor,
end: sliderTheme.activeTrackColor);
final ColorTween inactiveTrackColorTween = darkenInactive
? ColorTween(
begin: sliderTheme.disabledInactiveTrackColor,
end: sliderTheme.inactiveTrackColor
)
: activeTrackColorTween;
final Paint activePaint = Paint()
..shader = gradient.createShader(activeGradientRect)
..color = activeTrackColorTween.evaluate(enableAnimation)!;
final Paint inactivePaint = Paint()
..color = inactiveTrackColorTween.evaluate(enableAnimation)!;
final Paint leftTrackPaint;
final Paint rightTrackPaint;
switch (textDirection) {
case TextDirection.ltr:
leftTrackPaint = activePaint;
rightTrackPaint = inactivePaint;
break;
case TextDirection.rtl:
leftTrackPaint = inactivePaint;
rightTrackPaint = activePaint;
break;
}
final Radius trackRadius = Radius.circular(trackRect.height / 2);
final Radius activeTrackRadius = Radius.circular(trackRect.height / 2 + 1);
context.canvas.drawRRect(
RRect.fromLTRBAndCorners(
trackRect.left,
(textDirection == TextDirection.ltr)
? trackRect.top - (additionalActiveTrackHeight / 2)
: trackRect.top,
thumbCenter.dx,
(textDirection == TextDirection.ltr)
? trackRect.bottom + (additionalActiveTrackHeight / 2)
: trackRect.bottom,
topLeft: (textDirection == TextDirection.ltr)
? activeTrackRadius
: trackRadius,
bottomLeft: (textDirection == TextDirection.ltr)
? activeTrackRadius
: trackRadius,
),
leftTrackPaint,
);
context.canvas.drawRRect(
RRect.fromLTRBAndCorners(
thumbCenter.dx,
(textDirection == TextDirection.rtl)
? trackRect.top - (additionalActiveTrackHeight / 2)
: trackRect.top,
trackRect.right,
(textDirection == TextDirection.rtl)
? trackRect.bottom + (additionalActiveTrackHeight / 2)
: trackRect.bottom,
topRight: (textDirection == TextDirection.rtl)
? activeTrackRadius
: trackRadius,
bottomRight: (textDirection == TextDirection.rtl)
? activeTrackRadius
: trackRadius,
),
rightTrackPaint,
);
}
}
Solution 2
Use this library. It's really easy to implement with it,
https://pub.dev/packages/flutter_xlider
FlutterSlider(
values: [40],
max: 100,
min: 0,
trackBar: FlutterSliderTrackBar(
activeTrackBar: BoxDecoration(
gradient: AppColors.sliderGradient,
borderRadius: BorderRadius.circular(5)
),
activeTrackBarHeight: 6,
),
onDragging: (handlerIndex, lowerValue, upperValue) {
},
);
**Update
Seems like the pub version hasn't been updated to null safety. But the master branch has it. Use as below for null safety version
flutter_xlider:
git:
url: https://github.com/Ali-Azmoud/flutter_xlider.git
ref: master
Solution 3
You can try this;
Widget get gradientContainer => Container(
width: double.infinity,
height: height,
decoration: BoxDecoration(
gradient: gradient
),
);
Widget get slider =>SliderTheme(
data: SliderThemeData(
trackShape: CustomTrackShape(),
activeTrackColor: Colors.transparent,
inactiveTrackColor: Colors.red,
thumbColor: Colors.white,
overlayColor: Colors.transparent
),
child: Slider(
value: value,
max: max,
min: min,
onChanged: (double newValue){
setState(() {
value=newValue;
});
}
)
);
And for throw the track padding on slider, our custom track shape class is here too;
class CustomTrackShape extends RoundedRectSliderTrackShape {
Rect getPreferredRect({
@required RenderBox parentBox,
Offset offset = Offset.zero,
@required SliderThemeData sliderTheme,
bool isEnabled = false,
bool isDiscrete = false,
}) {
final double trackHeight = sliderTheme.trackHeight;
final double trackLeft = offset.dx;
final double trackTop = offset.dy + (parentBox.size.height - trackHeight) / 2;
final double trackWidth = parentBox.size.width;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
}
and we can finally merge them;
Widget get gradientSlider=>Padding(
child: SizedBox(
child: Stack(
children: [
gradientContainer,
slider,
],
alignment: Alignment.center,
),
),
padding: padding
);
and lastly you just must the fill padding, width, height, gradient button container height properties, just it.
CinePlays
Updated on December 24, 2022Comments
-
CinePlays over 1 year
I was wondering if there is a way of creating a slider widget in Flutter with a gradient color. Here is a link to the slider class, but there's no "SliderTheme" or something like that.
-
pskink over 3 yearswhat do you mean by
'but there's no "SliderTheme"'
? -
CinePlays over 3 yearse.g in a text widget you can add a style (TextTheme) to change the size, color and font.
-
pskink over 3 yearsapi.flutter.dev/flutter/material/SliderTheme-class.html - and if you dont have a local API docs installed you can always check api.flutter.dev/index.html - they have nice
Search API Docs
search field in the top right corner -
CinePlays over 3 yearsbut how can I add a gradient? There're only Color properties and no paint (text widget) or gradient property.
-
pskink over 3 yearscheck
*Shape
properties
-
-
Arslan Kaleem almost 3 yearsAlmost my problem is solved but I want to show colors till the nobe and inactive part will remain transparent
-
Arsen Tatraev over 2 yearsIt's good, but it is not Null safety now.
-
Kasun Thilina over 2 yearsThere's a null safety version in the github repo. I have updated the answer with that
-
Suj about 2 yearsthanks man for updating answer
-
Suj about 2 yearswork like charm Thanks man really appreciate.
-
Hitesh Kumar Saini about 2 yearsEpic answer. Take my upvote.