Cleanup OutlinedButton.icon documentation and implementation (#176630)

## Description

This PR cleanup `OutlinedButton.icon` documentation and recent logic
change from https://github.com/flutter/flutter/pull/175810.
This commit is contained in:
Bruno Leroux 2025-10-10 11:39:18 +02:00 committed by GitHub
parent 1969110cb6
commit 75df48ba1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 14 deletions

View File

@ -86,13 +86,14 @@ class OutlinedButton extends ButtonStyleButton {
required super.child,
}) : _addPadding = false;
/// Create a text button from a pair of widgets that serve as the button's
/// Create an outlined button from a pair of widgets that serve as the button's
/// [icon] and [label].
///
/// The icon and label are arranged in a row and padded by 12 logical pixels
/// at the start, and 16 at the end, with an 8 pixel gap in between.
///
/// If [icon] is null, will create an [OutlinedButton] instead.
/// If [icon] is null, this constructor will create an outlined button
/// that doesn't display an icon.
///
/// {@macro flutter.material.ButtonStyleButton.iconAlignment}
///
@ -114,10 +115,10 @@ class OutlinedButton extends ButtonStyleButton {
super(
child: icon != null
? _OutlinedButtonWithIconChild(
iconAlignment: iconAlignment,
label: label,
buttonStyle: style,
icon: icon,
buttonStyle: style,
iconAlignment: iconAlignment,
)
: label,
);
@ -419,13 +420,13 @@ EdgeInsetsGeometry _scaledPadding(BuildContext context) {
class _OutlinedButtonWithIconChild extends StatelessWidget {
const _OutlinedButtonWithIconChild({
required this.label,
this.icon,
required this.icon,
required this.buttonStyle,
required this.iconAlignment,
});
final Widget label;
final Widget? icon;
final Widget icon;
final ButtonStyle? buttonStyle;
final IconAlignment? iconAlignment;
@ -442,12 +443,6 @@ class _OutlinedButtonWithIconChild extends StatelessWidget {
outlinedButtonTheme.style?.iconAlignment ??
buttonStyle?.iconAlignment ??
IconAlignment.start;
final Widget? icon = this.icon;
if (icon == null) {
return label;
}
return Row(
mainAxisSize: MainAxisSize.min,
spacing: lerpDouble(8, 4, scale)!,

View File

@ -1295,7 +1295,7 @@ void main() {
// Initially, no icons are present.
expect(find.byIcon(Icons.favorite), findsNothing);
// Find the original OutlinedButton with no icon and get it's SemanticsNode
// Find the original OutlinedButton with no icon and get its SemanticsNode.
final Finder outlinedButton = find.bySemanticsLabel('Button');
expect(outlinedButton, findsOneWidget);
@ -1308,7 +1308,7 @@ void main() {
// Now one icon should be present.
expect(find.byIcon(Icons.favorite), findsOneWidget);
// Check if the semantics has change
// Check if the semantics has change.
final SemanticsNode semanticsNodeWithIcon = tester.getSemantics(outlinedButton);
expect(semanticsNodeWithIcon, origSemanticsNode);
@ -3047,4 +3047,33 @@ void main() {
matchesGoldenFile('outlined_button.badge.outline.png'),
);
});
testWidgets('OutlinedButton.icon does not lose focus when icon is nullified', (
WidgetTester tester,
) async {
Widget buildButton({required Widget? icon}) {
return MaterialApp(
home: Center(
child: OutlinedButton.icon(onPressed: () {}, icon: icon, label: const Text('button')),
),
);
}
// Build once with an icon.
await tester.pumpWidget(buildButton(icon: const Icon(Icons.abc)));
FocusNode getButtonFocusNode() {
return Focus.of(tester.element(find.text('button')));
}
getButtonFocusNode().requestFocus();
await tester.pumpAndSettle();
expect(getButtonFocusNode().hasFocus, true);
// Rebuild without icon.
await tester.pumpWidget(buildButton(icon: null));
// The button should still be focused.
expect(getButtonFocusNode().hasFocus, true);
});
}