Skip to content

Commit 9131115

Browse files
[Stepper] adds stepIconBuilder property (flutter#122816)
[Stepper] adds stepIconBuilder property
1 parent d74a1bb commit 9131115

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

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

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ class ControlsDetails {
106106
/// * [WidgetBuilder], which is similar but only takes a [BuildContext].
107107
typedef ControlsWidgetBuilder = Widget Function(BuildContext context, ControlsDetails details);
108108

109+
/// A builder that creates the icon widget for the [Step] at [stepIndex], given
110+
/// [stepState].
111+
typedef StepIconBuilder = Widget? Function(int stepIndex, StepState stepState);
112+
109113
const TextStyle _kStepStyle = TextStyle(
110114
fontSize: 12.0,
111115
color: Colors.white,
@@ -207,6 +211,7 @@ class Stepper extends StatefulWidget {
207211
this.controlsBuilder,
208212
this.elevation,
209213
this.margin,
214+
this.stepIconBuilder,
210215
}) : assert(0 <= currentStep && currentStep < steps.length);
211216

212217
/// The steps of the stepper whose titles, subtitles, icons always get shown.
@@ -303,9 +308,17 @@ class Stepper extends StatefulWidget {
303308
/// The elevation of this stepper's [Material] when [type] is [StepperType.horizontal].
304309
final double? elevation;
305310

306-
/// custom margin on vertical stepper.
311+
/// Custom margin on vertical stepper.
307312
final EdgeInsetsGeometry? margin;
308313

314+
/// Callback for creating custom icons for the [steps].
315+
///
316+
/// When overriding icon for [StepState.error], please return
317+
/// a widget whose width and height are 14 pixels or less to avoid overflow.
318+
///
319+
/// If null, the default icons will be used for respective [StepState].
320+
final StepIconBuilder? stepIconBuilder;
321+
309322
@override
310323
State<Stepper> createState() => _StepperState();
311324
}
@@ -373,6 +386,10 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
373386
Widget _buildCircleChild(int index, bool oldState) {
374387
final StepState state = oldState ? _oldStates[index]! : widget.steps[index].state;
375388
final bool isDarkActive = _isDark() && widget.steps[index].isActive;
389+
final Widget? icon = widget.stepIconBuilder?.call(index, state);
390+
if (icon != null) {
391+
return icon;
392+
}
376393
switch (state) {
377394
case StepState.indexed:
378395
case StepState.disabled:

packages/flutter/test/material/stepper_test.dart

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,48 @@ testWidgets('Stepper custom indexed controls test', (WidgetTester tester) async
12591259
tester.widget<Text>(find.text('Label ${index + 2}'));
12601260
expect(bodyMediumStyle, nextLabelTextWidget.style);
12611261
});
1262+
1263+
testWidgets('Stepper stepIconBuilder test', (WidgetTester tester) async {
1264+
await tester.pumpWidget(
1265+
MaterialApp(
1266+
home: Material(
1267+
child: Stepper(
1268+
stepIconBuilder: (int index, StepState state) {
1269+
if (state == StepState.complete) {
1270+
return const FlutterLogo(size: 18);
1271+
}
1272+
return null;
1273+
},
1274+
steps: const <Step>[
1275+
Step(
1276+
title: Text('A'),
1277+
state: StepState.complete,
1278+
content: SizedBox(width: 100.0, height: 100.0),
1279+
),
1280+
Step(
1281+
title: Text('B'),
1282+
state: StepState.editing,
1283+
content: SizedBox(width: 100.0, height: 100.0),
1284+
),
1285+
Step(
1286+
title: Text('C'),
1287+
state: StepState.error,
1288+
content: SizedBox(width: 100.0, height: 100.0),
1289+
),
1290+
],
1291+
),
1292+
),
1293+
),
1294+
);
1295+
1296+
/// Finds the overridden widget for StepState.complete
1297+
expect(find.byType(FlutterLogo), findsOneWidget);
1298+
1299+
/// StepState.editing and StepState.error should have a default icon
1300+
expect(find.byIcon(Icons.edit), findsOneWidget);
1301+
expect(find.text('!'), findsOneWidget);
1302+
});
1303+
12621304
}
12631305

12641306
class _TappableColorWidget extends StatefulWidget {

0 commit comments

Comments
 (0)