diff --git a/CHANGELOG.md b/CHANGELOG.md
index 830a5b0..9f2b056 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## [0.6.1] - July 23, 2021
+
+* Added `timeLabelPadding` parameter for putting some extra space between the time labels and progress bar.
+* Fixed a couple bugs with thumb position
+* Added thumb radius and label padding controls to the sample project
+
## [0.6.0] - July 20, 2021
* Made the thumb and rounded bar caps stay within bar bounds so that padding is maintained from side text (#13)
diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 1d526a1..919434a 100644
--- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
+ location = "self:">
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 7f0cb01..dad877f 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -61,6 +61,8 @@ class _HomeWidgetState extends State {
var _labelLocation = TimeLabelLocation.below;
var _labelType = TimeLabelType.totalTime;
TextStyle? _labelStyle;
+ var _thumbRadius = 10.0;
+ var _labelPadding = 0.0;
@override
void initState() {
@@ -93,7 +95,6 @@ class _HomeWidgetState extends State {
@override
Widget build(BuildContext context) {
- debugPrint('building app');
return Scaffold(
body: SafeArea(
child: Padding(
@@ -104,6 +105,8 @@ class _HomeWidgetState extends State {
_labelLocationButtons(),
_labelTypeButtons(),
_labelSizeButtons(),
+ _thumbSizeButtons(),
+ _paddingSizeButtons(),
const Spacer(),
_progressBar(),
_playButton(),
@@ -205,6 +208,52 @@ class _HomeWidgetState extends State {
]);
}
+ Wrap _thumbSizeButtons() {
+ return Wrap(children: [
+ OutlinedButton(
+ child: const Text('standard thumb radius'),
+ onPressed: () {
+ setState(() => _thumbRadius = 10);
+ },
+ ),
+ OutlinedButton(
+ child: const Text('large'),
+ onPressed: () {
+ setState(() => _thumbRadius = 20);
+ },
+ ),
+ OutlinedButton(
+ child: const Text('small'),
+ onPressed: () {
+ setState(() => _thumbRadius = 5);
+ },
+ ),
+ ]);
+ }
+
+ Wrap _paddingSizeButtons() {
+ return Wrap(children: [
+ OutlinedButton(
+ child: const Text('standard padding'),
+ onPressed: () {
+ setState(() => _labelPadding = 0.0);
+ },
+ ),
+ OutlinedButton(
+ child: const Text('10 padding'),
+ onPressed: () {
+ setState(() => _labelPadding = 10);
+ },
+ ),
+ OutlinedButton(
+ child: const Text('-5 padding'),
+ onPressed: () {
+ setState(() => _labelPadding = -5);
+ },
+ ),
+ ]);
+ }
+
StreamBuilder _progressBar() {
return StreamBuilder(
stream: _durationState,
@@ -220,9 +269,11 @@ class _HomeWidgetState extends State {
onSeek: (duration) {
_player.seek(duration);
},
+ thumbRadius: _thumbRadius,
timeLabelLocation: _labelLocation,
timeLabelType: _labelType,
timeLabelTextStyle: _labelStyle,
+ timeLabelPadding: _labelPadding,
);
},
);
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 3ec837e..dce9a32 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -21,7 +21,7 @@ packages:
path: ".."
relative: true
source: path
- version: "0.6.0"
+ version: "0.6.1"
boolean_selector:
dependency: transitive
description:
@@ -120,7 +120,7 @@ packages:
name: just_audio
url: "https://pub.dartlang.org"
source: hosted
- version: "0.9.2"
+ version: "0.9.3"
just_audio_platform_interface:
dependency: transitive
description:
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 02c76e6..9ae323f 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -13,7 +13,7 @@ dependencies:
sdk: flutter
audio_video_progress_bar:
path: ../
- just_audio: ^0.9.2
+ just_audio: ^0.9.3
rxdart: ^0.27.0
dev_dependencies:
diff --git a/lib/audio_video_progress_bar.dart b/lib/audio_video_progress_bar.dart
index dc40e72..5281979 100644
--- a/lib/audio_video_progress_bar.dart
+++ b/lib/audio_video_progress_bar.dart
@@ -81,6 +81,7 @@ class ProgressBar extends LeafRenderObjectWidget {
this.timeLabelLocation,
this.timeLabelType,
this.timeLabelTextStyle,
+ this.timeLabelPadding = 0.0,
}) : super(key: key);
/// The elapsed playing time of the media.
@@ -163,6 +164,12 @@ class ProgressBar extends LeafRenderObjectWidget {
/// By default it is [TextTheme.bodyText1].
final TextStyle? timeLabelTextStyle;
+ /// The extra space between the time labels and the progress bar.
+ ///
+ /// The default is 0.0. A positive number will move the labels further from
+ /// the progress bar and a negative number will move them closer.
+ final double timeLabelPadding;
+
@override
_RenderProgressBar createRenderObject(BuildContext context) {
final theme = Theme.of(context);
@@ -185,6 +192,7 @@ class ProgressBar extends LeafRenderObjectWidget {
timeLabelLocation: timeLabelLocation ?? TimeLabelLocation.below,
timeLabelType: timeLabelType ?? TimeLabelType.totalTime,
timeLabelTextStyle: textStyle,
+ timeLabelPadding: timeLabelPadding,
);
}
@@ -210,7 +218,8 @@ class ProgressBar extends LeafRenderObjectWidget {
..thumbGlowRadius = thumbGlowRadius
..timeLabelLocation = timeLabelLocation ?? TimeLabelLocation.below
..timeLabelType = timeLabelType ?? TimeLabelType.totalTime
- ..timeLabelTextStyle = textStyle;
+ ..timeLabelTextStyle = textStyle
+ ..timeLabelPadding = timeLabelPadding;
}
@override
@@ -234,6 +243,7 @@ class ProgressBar extends LeafRenderObjectWidget {
properties.add(StringProperty('timeLabelType', timeLabelType.toString()));
properties
.add(DiagnosticsProperty('timeLabelTextStyle', timeLabelTextStyle));
+ properties.add(DoubleProperty('timeLabelPadding', timeLabelPadding));
}
}
@@ -254,6 +264,7 @@ class _RenderProgressBar extends RenderBox {
required TimeLabelLocation timeLabelLocation,
required TimeLabelType timeLabelType,
TextStyle? timeLabelTextStyle,
+ double timeLabelPadding = 0.0,
}) : _progress = progress,
_total = total,
_buffered = buffered,
@@ -268,7 +279,8 @@ class _RenderProgressBar extends RenderBox {
_thumbGlowRadius = thumbGlowRadius,
_timeLabelLocation = timeLabelLocation,
_timeLabelType = timeLabelType,
- _timeLabelTextStyle = timeLabelTextStyle {
+ _timeLabelTextStyle = timeLabelTextStyle,
+ _timeLabelPadding = timeLabelPadding {
_drag = HorizontalDragGestureRecognizer()
..onStart = _onDragStart
..onUpdate = _onDragUpdate
@@ -318,11 +330,15 @@ class _RenderProgressBar extends RenderBox {
double barStart;
double barEnd;
if (_timeLabelLocation == TimeLabelLocation.sides) {
- barStart = _leftTimeLabel().width + _thumbRadius;
- barEnd = size.width - _rightTimeLabel().width - _thumbRadius;
+ barStart =
+ _leftTimeLabel().width + _defaultSidePadding + _timeLabelPadding;
+ barEnd = size.width -
+ _rightTimeLabel().width -
+ _defaultSidePadding -
+ _timeLabelPadding;
} else {
- barStart = _thumbRadius;
- barEnd = size.width - _thumbRadius;
+ barStart = 0;
+ barEnd = size.width;
}
final barWidth = barEnd - barStart;
final position = (dx - barStart).clamp(0.0, barWidth);
@@ -507,6 +523,20 @@ class _RenderProgressBar extends RenderBox {
markNeedsLayout();
}
+ /// The length of the radius for the circular thumb.
+ double get timeLabelPadding => _timeLabelPadding;
+ double _timeLabelPadding;
+ set timeLabelPadding(double value) {
+ if (_timeLabelPadding == value) return;
+ _timeLabelPadding = value;
+ markNeedsLayout();
+ }
+
+ // This padding is always used between the time labels and the progress bar
+ // when the time labels are on the sides. Any user defined [timeLabelPadding]
+ // is in addition to this.
+ static const _defaultSidePadding = 10;
+
// The smallest that this widget would ever want to be.
static const _minDesiredWidth = 100.0;
@@ -561,7 +591,7 @@ class _RenderProgressBar extends RenderBox {
}
double _heightWhenLabelsAboveOrBelow() {
- return _heightWhenNoLabels() + _textHeight();
+ return _heightWhenNoLabels() + _textHeight() + _timeLabelPadding;
}
double _heightWhenLabelsOnSides() {
@@ -618,7 +648,7 @@ class _RenderProgressBar extends RenderBox {
final isLabelBelow = _timeLabelLocation == TimeLabelLocation.below;
// current time label
- final labelDy = (isLabelBelow) ? barHeight : 0.0;
+ final labelDy = (isLabelBelow) ? barHeight + _timeLabelPadding : 0.0;
final leftLabelOffset = Offset(0, labelDy);
final leftTimeLabel = _leftTimeLabel();
leftTimeLabel.paint(canvas, leftLabelOffset);
@@ -630,7 +660,8 @@ class _RenderProgressBar extends RenderBox {
_rightTimeLabel().paint(canvas, rightLabelOffset);
// progress bar
- final barDy = (isLabelBelow) ? 0.0 : leftTimeLabel.height;
+ final barDy =
+ (isLabelBelow) ? 0.0 : leftTimeLabel.height + _timeLabelPadding;
_drawProgressBar(canvas, Offset(0, barDy), Size(barWidth, barHeight));
}
@@ -639,34 +670,30 @@ class _RenderProgressBar extends RenderBox {
/// | 01:23 -------O---------------- 05:00 |
///
void _drawProgressBarWithLabelsOnSides(Canvas canvas) {
- // calculate sizes
- const padding = 10;
- final barHeight = 2 * _thumbRadius;
-
- // painters
+ // left time label
final leftTimeLabel = _leftTimeLabel();
- final rightTimeLabel = _rightTimeLabel();
-
- // current time label
final verticalOffset = size.height / 2 - leftTimeLabel.height / 2;
- final currentLabelOffset = Offset(0, verticalOffset);
- leftTimeLabel.paint(canvas, currentLabelOffset);
+ final leftLabelOffset = Offset(0, verticalOffset);
+ leftTimeLabel.paint(canvas, leftLabelOffset);
- // total or remaining time label
- final totalLabelDx = size.width - rightTimeLabel.width;
+ // right time label
+ final rightTimeLabel = _rightTimeLabel();
+ final rightLabelWidth = rightTimeLabel.width;
+ final totalLabelDx = size.width - rightLabelWidth;
final totalLabelOffset = Offset(totalLabelDx, verticalOffset);
rightTimeLabel.paint(canvas, totalLabelOffset);
// progress bar
final leftLabelWidth = leftTimeLabel.width;
- final barWidth =
- size.width - 2 * padding - leftLabelWidth - rightTimeLabel.width;
+ final barHeight = 2 * _thumbRadius;
+ final barWidth = size.width -
+ 2 * _defaultSidePadding -
+ 2 * _timeLabelPadding -
+ leftLabelWidth -
+ rightLabelWidth;
final barDy = size.height / 2 - barHeight / 2;
- _drawProgressBar(
- canvas,
- Offset(padding + leftLabelWidth, barDy),
- Size(barWidth, barHeight),
- );
+ final barDx = leftLabelWidth + _defaultSidePadding + _timeLabelPadding;
+ _drawProgressBar(canvas, Offset(barDx, barDy), Size(barWidth, barHeight));
}
/// Draw the progress bar without labels like this:
@@ -735,8 +762,9 @@ class _RenderProgressBar extends RenderBox {
void _drawThumb(Canvas canvas, Size localSize) {
final thumbPaint = Paint()..color = thumbColor;
- final adjustedWidth = localSize.width - 2 * _thumbRadius;
- final thumbDx = _thumbValue * adjustedWidth + _thumbRadius;
+ final width = localSize.width;
+ final thumbDx =
+ (_thumbValue * width).clamp(_thumbRadius, width - _thumbRadius);
final center = Offset(thumbDx, localSize.height / 2);
if (_userIsDraggingThumb) {
final thumbGlowPaint = Paint()..color = thumbGlowColor;
diff --git a/pubspec.yaml b/pubspec.yaml
index b941361..1098f20 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,7 @@
name: audio_video_progress_bar
description: A progress bar widget to show or change the position of an audio or
video stream.
-version: 0.6.0
+version: 0.6.1
homepage: https://github.com/suragch/audio_video_progress_bar
environment:
diff --git a/test/audio_video_progress_bar_test.dart b/test/audio_video_progress_bar_test.dart
index 9557b0a..3e95dd9 100644
--- a/test/audio_video_progress_bar_test.dart
+++ b/test/audio_video_progress_bar_test.dart
@@ -58,6 +58,7 @@ void main() {
expect(progressBar.timeLabelType, TimeLabelType.remainingTime);
expect(progressBar.timeLabelTextStyle,
const TextStyle(color: Color(0x00000000)));
+ expect(progressBar.timeLabelPadding, 0.0);
});
testWidgets('TimeLabelLocation.below size correct',
@@ -201,4 +202,90 @@ void main() {
expect(baseSize.width, equals(800.0));
expect(baseSize.height, equals(14.0));
});
+
+ group('timeLabelPadding -', () {
+ testWidgets('Size with timeLabelPadding is correct when labels below',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(
+ const Center(
+ child: ProgressBar(
+ progress: Duration.zero,
+ total: Duration(minutes: 5),
+ timeLabelPadding: 10,
+ timeLabelLocation: TimeLabelLocation.below,
+ ),
+ ),
+ );
+
+ ProgressBar progressBar = tester.firstWidget(find.byType(ProgressBar));
+ expect(progressBar, isNotNull);
+
+ final baseSize = tester.getSize(find.byType(ProgressBar));
+ expect(baseSize.width, equals(800.0));
+ expect(baseSize.height, equals(44.0));
+ });
+
+ testWidgets('Size with timeLabelPadding is correct when labels above',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(
+ const Center(
+ child: ProgressBar(
+ progress: Duration.zero,
+ total: Duration(minutes: 5),
+ timeLabelPadding: 10,
+ timeLabelLocation: TimeLabelLocation.above,
+ ),
+ ),
+ );
+
+ ProgressBar progressBar = tester.firstWidget(find.byType(ProgressBar));
+ expect(progressBar, isNotNull);
+
+ final baseSize = tester.getSize(find.byType(ProgressBar));
+ expect(baseSize.width, equals(800.0));
+ expect(baseSize.height, equals(44.0));
+ });
+
+ testWidgets('Size with timeLabelPadding is correct when labels on sides',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(
+ const Center(
+ child: ProgressBar(
+ progress: Duration.zero,
+ total: Duration(minutes: 5),
+ timeLabelPadding: 10,
+ timeLabelLocation: TimeLabelLocation.sides,
+ ),
+ ),
+ );
+
+ ProgressBar progressBar = tester.firstWidget(find.byType(ProgressBar));
+ expect(progressBar, isNotNull);
+
+ final baseSize = tester.getSize(find.byType(ProgressBar));
+ expect(baseSize.width, equals(800.0));
+ expect(baseSize.height, equals(20.0));
+ });
+
+ testWidgets('Size with timeLabelPadding is correct when no labels',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(
+ const Center(
+ child: ProgressBar(
+ progress: Duration.zero,
+ total: Duration(minutes: 5),
+ timeLabelPadding: 10,
+ timeLabelLocation: TimeLabelLocation.none,
+ ),
+ ),
+ );
+
+ ProgressBar progressBar = tester.firstWidget(find.byType(ProgressBar));
+ expect(progressBar, isNotNull);
+
+ final baseSize = tester.getSize(find.byType(ProgressBar));
+ expect(baseSize.width, equals(800.0));
+ expect(baseSize.height, equals(20.0));
+ });
+ });
}