Context
I'm working on a custom slider widget in Flutter where I need the slider track to change its thickness slightly in an increasing way. I have not found any built-in properties in the Slider widget that could help achieve this effect. The thickness should increase as it gets closer to the end and decrease as it moves towards the start.
What I tried
I tried to create a custom SliderTheme and change the trackShape, here's the relevant code:
class CustomSliderTrackShape extends RoundedRectSliderTrackShape {
final double overlayWidth;
const CustomSliderTrackShape({
this.overlayWidth = 30.0,
});
@override
Rect getPreferredRect({
required RenderBox parentBox,
Offset offset = Offset.zero,
required SliderThemeData sliderTheme,
bool isEnabled = false,
bool isDiscrete = false,
}) {
final double overlayRadius = overlayWidth / 2;
final double trackLeft = offset.dx + overlayRadius;
final double trackTop = offset.dy + (parentBox.size.height / 2);
final double trackHeight = sliderTheme.trackHeight!;
// --> not sure how to increase the width of the track
final double trackWidth = parentBox.size.width - (2 * overlayRadius) + 10;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
}
And it's usage:
SliderTheme(
data: SliderTheme.of(context).copyWith(
// --> Using it here.
trackShape: CustomSliderTrackShape(),
),
child: Slider(
value: 0.4,
onChanged: (newValue) {},
),
)
which results in (seems like the regular Slider):
However, the desired output is:
Question
How can I modify the getPreferredRect function to create a custom slider that increases its height/thickness as it comes to the end? should I be using CustomPaint instead in order to achieve a slider with varying track thickness?
Here's the code as a fully runnable snippet:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Custom Slider Example')),
body: MySlider(),
),
);
}
}
class MySlider extends StatefulWidget {
@override
_MySliderState createState() => _MySliderState();
}
class _MySliderState extends State<MySlider> {
double _value = 50;
@override
Widget build(BuildContext context) {
return SliderTheme(
data: SliderTheme.of(context).copyWith(
trackHeight: 6,
trackShape: CustomSliderTrackShape(),
),
child: Slider(
min: 0,
max: 100,
divisions: 100,
value: _value,
onChanged: (value) {
setState(() {
_value = value;
});
},
),
);
}
}
class CustomSliderTrackShape extends RoundedRectSliderTrackShape {
final double overlayWidth;
const CustomSliderTrackShape({
this.overlayWidth = 30.0,
});
@override
Rect getPreferredRect({
required RenderBox parentBox,
Offset offset = Offset.zero,
required SliderThemeData sliderTheme,
bool isEnabled = false,
bool isDiscrete = false,
}) {
final double overlayRadius = overlayWidth / 2;
final double trackLeft = offset.dx + overlayRadius;
final double trackTop = offset.dy + (parentBox.size.height / 2);
final double trackHeight = sliderTheme.trackHeight!;
// --> not sure how to increase the width of the track
final double trackWidth = parentBox.size.width - (2 * overlayRadius) + 10;
return Rect.fromLTWH(trackLeft, trackTop, trackWidth, trackHeight);
}
}


You can play with
Paint, hope this help. Also try to find better ratio for your case,DartPad