Reputation: 1681
I have a min
and max
parameter which each require a double.
min: 0,
max: _duration!.inMilliseconds
These parameters are then converted to strings for use as dynamic text on top of the thumb ball of a slider.
But for the max
value I'd like to use the actual duration instead;
IE: 1:34:30 instead of 94,500.
The final product required is a String.
So how do I get the Duration to a string while preserving the Duration formatting?
Keep in mind it is passed initially as a double.
Here's the full class for the thumb ball;
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,
//fontWeight: FontWeight.w700,
color: Colors.white, //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));
final rect = Rect.fromCircle(center: center, radius: thumbRadius);
final rrect = RRect.fromRectAndRadius(
Rect.fromPoints(
Offset(rect.left - 10, rect.top),
Offset(rect.right + 10, rect.bottom),
),
Radius.elliptical(20, 100),
);
final fillPaint = Paint()
..color = sliderTheme!.activeTrackColor!
..style = PaintingStyle.fill;
final borderPaint = Paint()
..color = Colors.black
..strokeWidth = 2.8
..style = PaintingStyle.stroke;
canvas.drawRRect(rrect, fillPaint);
canvas.drawRRect(rrect, borderPaint);
tp.paint(canvas, textCenter);
}
String getValue(double value) {
return (min + (max - min) * value).round().toString();
}
}
Upvotes: 0
Views: 496
Reputation: 90015
If CustomSliderThumbCircle
is your own class, I would change it to take a callback function to format the value to a String
(falling back to just .toString()
if no callback is specified), something like:
class CustomSliderThumbCircle extends SliderComponentShape {
final String Function(int value)? formatValue;
...
const CustomSliderThumbCircle({
required this.thumbRadius,
this.min = 0,
this.max = 10,
this.formatValue,
});
String getValue(double value) {
var clamped = (min + (max - min) * value).round();
return (formatValue == null) ? clamped.toString() : formatValue!(clamped);
}
}
and then your caller could pass a callback:
CustomSliderThumbCircle(
thumbRadius: ...,
...,
formatValue: (value) => Duration(milliseconds: value).toString(),
)
This also would allow you to use a function that formats Duration
s as, say, 1m34.5s instead of as 0:01:34.500000. I generally dislike representing durations with colons because it can be ambiguous if fractional seconds are omitted. For example, using a different function to format Duration
s:
CustomSliderThumbCircle(
thumbRadius: ...,
...,
formatValue: (value) => prettyDuration(Duration(milliseconds: value)),
)
If CustomSliderThumbCircle
is not under your control, then you could extend it with your own class that overrides getValue
.
Upvotes: 1
Reputation: 1681
I doubt this is better than jamesdlin's solution but I don't know how to format it the way I'd like using the call back. Plus I realised I only need seconds and milliseconds as the audio is limited to 60 seconds anyway. So here's what I did;
String getValue(double value) {
double seconds = value * (max/1000);
String secstring = secs.truncate().toString();
var milliseconds = value * (max.remainder(1000));
String millistring = milliseconds.truncate().toString();
String stringDuration = secstring + ':' + millistring;
return stringDuration ;
}
Upvotes: 0