Skip to content

Commit 9e9ac77

Browse files
authored
Add borderRadius to LinearProgressIndicator (#123517)
Split from flutter/flutter#122664 so it gets easier to review, as this is now unrelated to the `preferRound`. I'm one step from adding a width attribute, lol. <img width="474" alt="image" src="https://user-images.githubusercontent.com/351125/226083798-71e529e9-4ae9-41de-a500-0412b989a273.png"> cc @Piinks
1 parent aa5bb7d commit 9e9ac77

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

packages/flutter/lib/src/material/progress_indicator.dart

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,15 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
145145
this.value,
146146
required this.animationValue,
147147
required this.textDirection,
148+
required this.indicatorBorderRadius,
148149
});
149150

150151
final Color backgroundColor;
151152
final Color valueColor;
152153
final double? value;
153154
final double animationValue;
154155
final TextDirection textDirection;
156+
final BorderRadiusGeometry indicatorBorderRadius;
155157

156158
// The indeterminate progress animation displays two lines whose leading (head)
157159
// and trailing (tail) endpoints are defined by the following four curves.
@@ -181,7 +183,6 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
181183
final Paint paint = Paint()
182184
..color = backgroundColor
183185
..style = PaintingStyle.fill;
184-
canvas.drawRect(Offset.zero & size, paint);
185186

186187
paint.color = valueColor;
187188

@@ -197,7 +198,14 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
197198
case TextDirection.ltr:
198199
left = x;
199200
}
200-
canvas.drawRect(Offset(left, 0.0) & Size(width, size.height), paint);
201+
202+
final Rect rect = Offset(left, 0.0) & Size(width, size.height);
203+
if (indicatorBorderRadius != BorderRadius.zero) {
204+
final RRect rrect = indicatorBorderRadius.resolve(textDirection).toRRect(rect);
205+
canvas.drawRRect(rrect, paint);
206+
} else {
207+
canvas.drawRect(rect, paint);
208+
}
201209
}
202210

203211
if (value != null) {
@@ -220,7 +228,8 @@ class _LinearProgressIndicatorPainter extends CustomPainter {
220228
|| oldPainter.valueColor != valueColor
221229
|| oldPainter.value != value
222230
|| oldPainter.animationValue != animationValue
223-
|| oldPainter.textDirection != textDirection;
231+
|| oldPainter.textDirection != textDirection
232+
|| oldPainter.indicatorBorderRadius != indicatorBorderRadius;
224233
}
225234
}
226235

@@ -279,6 +288,7 @@ class LinearProgressIndicator extends ProgressIndicator {
279288
this.minHeight,
280289
super.semanticsLabel,
281290
super.semanticsValue,
291+
this.borderRadius = BorderRadius.zero,
282292
}) : assert(minHeight == null || minHeight > 0);
283293

284294
/// {@template flutter.material.LinearProgressIndicator.trackColor}
@@ -301,6 +311,12 @@ class LinearProgressIndicator extends ProgressIndicator {
301311
/// {@endtemplate}
302312
final double? minHeight;
303313

314+
/// The border radius of both the indicator and the track.
315+
///
316+
/// By default it is [BorderRadius.zero], which produces a rectangular shape
317+
/// with a rectangular indicator.
318+
final BorderRadiusGeometry borderRadius;
319+
304320
@override
305321
State<LinearProgressIndicator> createState() => _LinearProgressIndicatorState();
306322
}
@@ -352,6 +368,14 @@ class _LinearProgressIndicatorState extends State<LinearProgressIndicator> with
352368
return widget._buildSemanticsWrapper(
353369
context: context,
354370
child: Container(
371+
// Clip is only needed with indeterminate progress indicators
372+
clipBehavior: (widget.borderRadius != BorderRadius.zero && widget.value == null)
373+
? Clip.antiAlias
374+
: Clip.none,
375+
decoration: ShapeDecoration(
376+
color: trackColor,
377+
shape: RoundedRectangleBorder(borderRadius: widget.borderRadius),
378+
),
355379
constraints: BoxConstraints(
356380
minWidth: double.infinity,
357381
minHeight: minHeight,
@@ -363,6 +387,7 @@ class _LinearProgressIndicatorState extends State<LinearProgressIndicator> with
363387
value: widget.value, // may be null
364388
animationValue: animationValue, // ignored if widget.value is not null
365389
textDirection: textDirection,
390+
indicatorBorderRadius: widget.borderRadius,
366391
),
367392
),
368393
),

packages/flutter/test/material/progress_indicator_test.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,41 @@ void main() {
465465
expect(find.byType(CircularProgressIndicator), paints..arc(strokeCap: StrokeCap.round));
466466
});
467467

468+
testWidgets('LinearProgressIndicator with indicatorBorderRadius', (WidgetTester tester) async {
469+
await tester.pumpWidget(
470+
Theme(
471+
data: theme,
472+
child: const Directionality(
473+
textDirection: TextDirection.ltr,
474+
child: Center(
475+
child: SizedBox(
476+
width: 100.0,
477+
height: 4.0,
478+
child: LinearProgressIndicator(
479+
value: 0.25,
480+
borderRadius: BorderRadius.all(Radius.circular(10)),
481+
),
482+
),
483+
),
484+
),
485+
),
486+
);
487+
expect(
488+
find.byType(LinearProgressIndicator),
489+
paints
490+
..rrect(
491+
rrect: RRect.fromLTRBR(0.0, 0.0, 100.0, 4.0, const Radius.circular(10.0)),
492+
)
493+
..rrect(
494+
rrect: RRect.fromRectAndRadius(
495+
const Rect.fromLTRB(0.0, 0.0, 25.0, 4.0),
496+
const Radius.circular(10.0),
497+
),
498+
),
499+
);
500+
expect(tester.binding.transientCallbackCount, 0);
501+
});
502+
468503
testWidgets('CircularProgressIndicator paint colors', (WidgetTester tester) async {
469504
const Color green = Color(0xFF00FF00);
470505
const Color blue = Color(0xFF0000FF);

0 commit comments

Comments
 (0)