Update ToggleButtons constraints default and add new constraints parameter (#39857) * Add constraints property, updated default constraints for ToggleButtons to 48x48 * Add kMinInteractiveDimension constant to ToggleButtons
diff --git a/packages/flutter/lib/src/material/toggle_buttons.dart b/packages/flutter/lib/src/material/toggle_buttons.dart index 66d29e2..9671901 100644 --- a/packages/flutter/lib/src/material/toggle_buttons.dart +++ b/packages/flutter/lib/src/material/toggle_buttons.dart
@@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart'; import 'button.dart'; +import 'constants.dart'; import 'debug.dart'; import 'theme.dart'; import 'theme_data.dart'; @@ -166,6 +167,7 @@ @required this.isSelected, this.onPressed, this.textStyle, + this.constraints, this.color, this.selectedColor, this.disabledColor, @@ -223,6 +225,14 @@ /// are active, selected, or disabled. final TextStyle textStyle; + /// Defines the button's size. + /// + /// Typically used to constrain the button's minimum size. + /// + /// If this property is null, then + /// BoxConstraints(minWidth: 48.0, minHeight: 48.0) is be used. + final BoxConstraints constraints; + /// The color for descendant [Text] and [Icon] widgets if the button is /// enabled and not selected. /// @@ -578,6 +588,7 @@ return _ToggleButton( selected: isSelected[index], textStyle: textStyle, + constraints: constraints, color: color, selectedColor: selectedColor, disabledColor: disabledColor, @@ -645,6 +656,7 @@ Key key, this.selected = false, this.textStyle, + this.constraints, this.color, this.selectedColor, this.disabledColor, @@ -671,6 +683,11 @@ /// The [TextStyle] to apply to any text that appears in this button. final TextStyle textStyle; + /// Defines the button's size. + /// + /// Typically used to constrain the button's minimum size. + final BoxConstraints constraints; + /// The color for [Text] and [Icon] widgets if the button is enabled. /// /// If [selected] is false and [onPressed] is not null, this color will be used. @@ -784,6 +801,7 @@ } final TextStyle currentTextStyle = textStyle ?? toggleButtonsTheme.textStyle ?? theme.textTheme.body1; + final BoxConstraints currentConstraints = constraints ?? toggleButtonsTheme.constraints ?? const BoxConstraints(minWidth: kMinInteractiveDimension, minHeight: kMinInteractiveDimension); final Widget result = ClipRRect( borderRadius: clipRadius, @@ -791,6 +809,7 @@ textStyle: currentTextStyle.copyWith( color: currentColor, ), + constraints: currentConstraints, elevation: 0.0, highlightElevation: 0.0, fillColor: currentFillColor,
diff --git a/packages/flutter/lib/src/material/toggle_buttons_theme.dart b/packages/flutter/lib/src/material/toggle_buttons_theme.dart index d80b6ed..865667f 100644 --- a/packages/flutter/lib/src/material/toggle_buttons_theme.dart +++ b/packages/flutter/lib/src/material/toggle_buttons_theme.dart
@@ -29,6 +29,7 @@ /// [ToggleButtons]. const ToggleButtonsThemeData({ this.textStyle, + this.constraints, this.color, this.selectedColor, this.disabledColor, @@ -51,6 +52,11 @@ /// are active, selected, or disabled. final TextStyle textStyle; + /// Defines the button's size. + /// + /// Typically used to constrain the button's minimum size. + final BoxConstraints constraints; + /// The color for descendant [Text] and [Icon] widgets if the toggle button /// is enabled. final Color color; @@ -104,6 +110,7 @@ /// new values. ToggleButtonsThemeData copyWith({ TextStyle textStyle, + BoxConstraints constraints, Color color, Color selectedColor, Color disabledColor, @@ -120,6 +127,7 @@ }) { return ToggleButtonsThemeData( textStyle: textStyle ?? this.textStyle, + constraints: constraints ?? this.constraints, color: color ?? this.color, selectedColor: selectedColor ?? this.selectedColor, disabledColor: disabledColor ?? this.disabledColor, @@ -143,6 +151,7 @@ return null; return ToggleButtonsThemeData( textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t), + constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t), color: Color.lerp(a?.color, b?.color, t), selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t), disabledColor: Color.lerp(a?.disabledColor, b?.disabledColor, t), @@ -163,6 +172,7 @@ int get hashCode { return hashValues( textStyle, + constraints, color, selectedColor, disabledColor, @@ -187,6 +197,7 @@ return false; final ToggleButtonsThemeData typedOther = other; return typedOther.textStyle == textStyle + && typedOther.constraints == constraints && typedOther.color == color && typedOther.selectedColor == selectedColor && typedOther.disabledColor == disabledColor @@ -206,6 +217,7 @@ void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); textStyle?.debugFillProperties(properties, prefix: 'textStyle.'); + properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null)); properties.add(ColorProperty('color', color, defaultValue: null)); properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null)); properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null));
diff --git a/packages/flutter/test/material/toggle_buttons_test.dart b/packages/flutter/test/material/toggle_buttons_test.dart index f7eafa8..14a8fb4 100644 --- a/packages/flutter/test/material/toggle_buttons_test.dart +++ b/packages/flutter/test/material/toggle_buttons_test.dart
@@ -309,6 +309,98 @@ expect(textStyle.color, isNot(Colors.orange)); }); + testWidgets('Default BoxConstraints', (WidgetTester tester) async { + await tester.pumpWidget( + Material( + child: boilerplate( + child: ToggleButtons( + isSelected: const <bool>[false, false, false], + onPressed: (int index) {}, + children: const <Widget>[ + Icon(Icons.check), + Icon(Icons.access_alarm), + Icon(Icons.cake), + ], + ), + ), + ), + ); + + final Rect firstRect = tester.getRect(find.byType(RawMaterialButton).at(0)); + expect(firstRect.width, 48.0); + expect(firstRect.height, 48.0); + final Rect secondRect = tester.getRect(find.byType(RawMaterialButton).at(1)); + expect(secondRect.width, 48.0); + expect(secondRect.height, 48.0); + final Rect thirdRect = tester.getRect(find.byType(RawMaterialButton).at(2)); + expect(thirdRect.width, 48.0); + expect(thirdRect.height, 48.0); + }); + + testWidgets('Custom BoxConstraints', (WidgetTester tester) async { + // Test for minimum constraints + await tester.pumpWidget( + Material( + child: boilerplate( + child: ToggleButtons( + constraints: const BoxConstraints( + minWidth: 50.0, + minHeight: 60.0, + ), + isSelected: const <bool>[false, false, false], + onPressed: (int index) {}, + children: const <Widget>[ + Icon(Icons.check), + Icon(Icons.access_alarm), + Icon(Icons.cake), + ], + ), + ), + ), + ); + + Rect firstRect = tester.getRect(find.byType(RawMaterialButton).at(0)); + expect(firstRect.width, 50.0); + expect(firstRect.height, 60.0); + Rect secondRect = tester.getRect(find.byType(RawMaterialButton).at(1)); + expect(secondRect.width, 50.0); + expect(secondRect.height, 60.0); + Rect thirdRect = tester.getRect(find.byType(RawMaterialButton).at(2)); + expect(thirdRect.width, 50.0); + expect(thirdRect.height, 60.0); + + // Test for maximum constraints + await tester.pumpWidget( + Material( + child: boilerplate( + child: ToggleButtons( + constraints: const BoxConstraints( + maxWidth: 20.0, + maxHeight: 10.0, + ), + isSelected: const <bool>[false, false, false], + onPressed: (int index) {}, + children: const <Widget>[ + Icon(Icons.check), + Icon(Icons.access_alarm), + Icon(Icons.cake), + ], + ), + ), + ), + ); + + firstRect = tester.getRect(find.byType(RawMaterialButton).at(0)); + expect(firstRect.width, 20.0); + expect(firstRect.height, 10.0); + secondRect = tester.getRect(find.byType(RawMaterialButton).at(1)); + expect(secondRect.width, 20.0); + expect(secondRect.height, 10.0); + thirdRect = tester.getRect(find.byType(RawMaterialButton).at(2)); + expect(thirdRect.width, 20.0); + expect(thirdRect.height, 10.0); + }); + testWidgets( 'Default text/icon colors for enabled, selected and disabled states', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/toggle_buttons_theme_test.dart b/packages/flutter/test/material/toggle_buttons_theme_test.dart index 6c75220..15ecacf 100644 --- a/packages/flutter/test/material/toggle_buttons_theme_test.dart +++ b/packages/flutter/test/material/toggle_buttons_theme_test.dart
@@ -25,6 +25,7 @@ test('ToggleButtonsThemeData defaults', () { const ToggleButtonsThemeData themeData = ToggleButtonsThemeData(); expect(themeData.textStyle, null); + expect(themeData.constraints, null); expect(themeData.color, null); expect(themeData.selectedColor, null); expect(themeData.disabledColor, null); @@ -41,6 +42,7 @@ const ToggleButtonsTheme theme = ToggleButtonsTheme(data: ToggleButtonsThemeData()); expect(theme.data.textStyle, null); + expect(theme.data.constraints, null); expect(theme.data.color, null); expect(theme.data.selectedColor, null); expect(theme.data.disabledColor, null); @@ -72,6 +74,7 @@ final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); const ToggleButtonsThemeData( textStyle: TextStyle(fontSize: 10), + constraints: BoxConstraints(minHeight: 10.0, maxHeight: 20.0), color: Color(0xfffffff0), selectedColor: Color(0xfffffff1), disabledColor: Color(0xfffffff2), @@ -95,6 +98,7 @@ expect(description, <String>[ 'textStyle.inherit: true', 'textStyle.size: 10.0', + 'constraints: BoxConstraints(0.0<=w<=Infinity, 10.0<=h<=20.0)', 'color: Color(0xfffffff0)', 'selectedColor: Color(0xfffffff1)', 'disabledColor: Color(0xfffffff2)', @@ -154,6 +158,78 @@ expect(textStyle.color, isNot(Colors.orange)); }); + testWidgets('Custom BoxConstraints', (WidgetTester tester) async { + // Test for minimum constraints + await tester.pumpWidget( + Material( + child: boilerplate( + child: ToggleButtonsTheme( + data: const ToggleButtonsThemeData( + constraints: BoxConstraints( + minWidth: 50.0, + minHeight: 60.0, + ), + ), + child: ToggleButtons( + isSelected: const <bool>[false, false, false], + onPressed: (int index) {}, + children: const <Widget>[ + Icon(Icons.check), + Icon(Icons.access_alarm), + Icon(Icons.cake), + ], + ), + ), + ), + ), + ); + + Rect firstRect = tester.getRect(find.byType(RawMaterialButton).at(0)); + expect(firstRect.width, 50.0); + expect(firstRect.height, 60.0); + Rect secondRect = tester.getRect(find.byType(RawMaterialButton).at(1)); + expect(secondRect.width, 50.0); + expect(secondRect.height, 60.0); + Rect thirdRect = tester.getRect(find.byType(RawMaterialButton).at(2)); + expect(thirdRect.width, 50.0); + expect(thirdRect.height, 60.0); + + // Test for maximum constraints + await tester.pumpWidget( + Material( + child: boilerplate( + child: ToggleButtonsTheme( + data: const ToggleButtonsThemeData( + constraints: BoxConstraints( + maxWidth: 20.0, + maxHeight: 10.0, + ), + ), + child: ToggleButtons( + isSelected: const <bool>[false, false, false], + onPressed: (int index) {}, + children: const <Widget>[ + Icon(Icons.check), + Icon(Icons.access_alarm), + Icon(Icons.cake), + ], + ), + ), + ), + ), + ); + + firstRect = tester.getRect(find.byType(RawMaterialButton).at(0)); + expect(firstRect.width, 20.0); + expect(firstRect.height, 10.0); + secondRect = tester.getRect(find.byType(RawMaterialButton).at(1)); + expect(secondRect.width, 20.0); + expect(secondRect.height, 10.0); + thirdRect = tester.getRect(find.byType(RawMaterialButton).at(2)); + expect(thirdRect.width, 20.0); + expect(thirdRect.height, 10.0); + }); + testWidgets( 'Theme text/icon colors for enabled, selected and disabled states', (WidgetTester tester) async {