Unverified Commit b7abf56a authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

Add ToggleButtons.textStyle property (#38813)

* Add ToggleButtons.textStyle property
parent 878fe20a
...@@ -165,6 +165,7 @@ class ToggleButtons extends StatelessWidget { ...@@ -165,6 +165,7 @@ class ToggleButtons extends StatelessWidget {
@required this.children, @required this.children,
@required this.isSelected, @required this.isSelected,
this.onPressed, this.onPressed,
this.textStyle,
this.color, this.color,
this.selectedColor, this.selectedColor,
this.disabledColor, this.disabledColor,
...@@ -215,6 +216,13 @@ class ToggleButtons extends StatelessWidget { ...@@ -215,6 +216,13 @@ class ToggleButtons extends StatelessWidget {
/// When the callback is null, all toggle buttons will be disabled. /// When the callback is null, all toggle buttons will be disabled.
final void Function(int index) onPressed; final void Function(int index) onPressed;
/// The [TextStyle] to apply to any text in these toggle buttons.
///
/// [TextStyle.color] will be ignored and substituted by [color],
/// [selectedColor] or [disabledColor] depending on whether the buttons
/// are active, selected, or disabled.
final TextStyle textStyle;
/// The color for descendant [Text] and [Icon] widgets if the button is /// The color for descendant [Text] and [Icon] widgets if the button is
/// enabled and not selected. /// enabled and not selected.
/// ///
...@@ -569,6 +577,7 @@ class ToggleButtons extends StatelessWidget { ...@@ -569,6 +577,7 @@ class ToggleButtons extends StatelessWidget {
return _ToggleButton( return _ToggleButton(
selected: isSelected[index], selected: isSelected[index],
textStyle: textStyle,
color: color, color: color,
selectedColor: selectedColor, selectedColor: selectedColor,
disabledColor: disabledColor, disabledColor: disabledColor,
...@@ -603,6 +612,7 @@ class ToggleButtons extends StatelessWidget { ...@@ -603,6 +612,7 @@ class ToggleButtons extends StatelessWidget {
ifTrue: 'Buttons are disabled', ifTrue: 'Buttons are disabled',
ifFalse: 'Buttons are enabled', ifFalse: 'Buttons are enabled',
)); ));
textStyle?.debugFillProperties(properties, prefix: 'textStyle.');
properties.add(ColorProperty('color', color, defaultValue: null)); properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null)); properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null));
properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null)); properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null));
...@@ -634,6 +644,7 @@ class _ToggleButton extends StatelessWidget { ...@@ -634,6 +644,7 @@ class _ToggleButton extends StatelessWidget {
const _ToggleButton({ const _ToggleButton({
Key key, Key key,
this.selected = false, this.selected = false,
this.textStyle,
this.color, this.color,
this.selectedColor, this.selectedColor,
this.disabledColor, this.disabledColor,
...@@ -657,6 +668,9 @@ class _ToggleButton extends StatelessWidget { ...@@ -657,6 +668,9 @@ class _ToggleButton extends StatelessWidget {
/// Determines if the button is displayed as active/selected or enabled. /// Determines if the button is displayed as active/selected or enabled.
final bool selected; final bool selected;
/// The [TextStyle] to apply to any text that appears in this button.
final TextStyle textStyle;
/// The color for [Text] and [Icon] widgets if the button is enabled. /// 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. /// If [selected] is false and [onPressed] is not null, this color will be used.
...@@ -769,10 +783,12 @@ class _ToggleButton extends StatelessWidget { ...@@ -769,10 +783,12 @@ class _ToggleButton extends StatelessWidget {
currentFillColor = theme.colorScheme.surface.withOpacity(0.0); currentFillColor = theme.colorScheme.surface.withOpacity(0.0);
} }
final TextStyle currentTextStyle = textStyle ?? toggleButtonsTheme.textStyle ?? theme.textTheme.body1;
final Widget result = ClipRRect( final Widget result = ClipRRect(
borderRadius: clipRadius, borderRadius: clipRadius,
child: RawMaterialButton( child: RawMaterialButton(
textStyle: TextStyle( textStyle: currentTextStyle.copyWith(
color: currentColor, color: currentColor,
), ),
elevation: 0.0, elevation: 0.0,
......
...@@ -28,6 +28,7 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -28,6 +28,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
/// Creates the set of color and border properties used to configure /// Creates the set of color and border properties used to configure
/// [ToggleButtons]. /// [ToggleButtons].
const ToggleButtonsThemeData({ const ToggleButtonsThemeData({
this.textStyle,
this.color, this.color,
this.selectedColor, this.selectedColor,
this.disabledColor, this.disabledColor,
...@@ -43,6 +44,13 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -43,6 +44,13 @@ class ToggleButtonsThemeData extends Diagnosticable {
this.borderWidth, this.borderWidth,
}); });
/// The default text style for [ToggleButtons.children].
///
/// [TextStyle.color] will be ignored and substituted by [color],
/// [selectedColor] or [disabledColor] depending on whether the buttons
/// are active, selected, or disabled.
final TextStyle textStyle;
/// The color for descendant [Text] and [Icon] widgets if the toggle button /// The color for descendant [Text] and [Icon] widgets if the toggle button
/// is enabled. /// is enabled.
final Color color; final Color color;
...@@ -95,6 +103,7 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -95,6 +103,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
/// Creates a copy of this object but with the given fields replaced with the /// Creates a copy of this object but with the given fields replaced with the
/// new values. /// new values.
ToggleButtonsThemeData copyWith({ ToggleButtonsThemeData copyWith({
TextStyle textStyle,
Color color, Color color,
Color selectedColor, Color selectedColor,
Color disabledColor, Color disabledColor,
...@@ -110,6 +119,7 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -110,6 +119,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
double borderWidth, double borderWidth,
}) { }) {
return ToggleButtonsThemeData( return ToggleButtonsThemeData(
textStyle: textStyle ?? this.textStyle,
color: color ?? this.color, color: color ?? this.color,
selectedColor: selectedColor ?? this.selectedColor, selectedColor: selectedColor ?? this.selectedColor,
disabledColor: disabledColor ?? this.disabledColor, disabledColor: disabledColor ?? this.disabledColor,
...@@ -132,6 +142,7 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -132,6 +142,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
if (a == null && b == null) if (a == null && b == null)
return null; return null;
return ToggleButtonsThemeData( return ToggleButtonsThemeData(
textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t),
color: Color.lerp(a?.color, b?.color, t), color: Color.lerp(a?.color, b?.color, t),
selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t), selectedColor: Color.lerp(a?.selectedColor, b?.selectedColor, t),
disabledColor: Color.lerp(a?.disabledColor, b?.disabledColor, t), disabledColor: Color.lerp(a?.disabledColor, b?.disabledColor, t),
...@@ -151,6 +162,7 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -151,6 +162,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
@override @override
int get hashCode { int get hashCode {
return hashValues( return hashValues(
textStyle,
color, color,
selectedColor, selectedColor,
disabledColor, disabledColor,
...@@ -174,7 +186,8 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -174,7 +186,8 @@ class ToggleButtonsThemeData extends Diagnosticable {
if (other.runtimeType != runtimeType) if (other.runtimeType != runtimeType)
return false; return false;
final ToggleButtonsThemeData typedOther = other; final ToggleButtonsThemeData typedOther = other;
return typedOther.color == color return typedOther.textStyle == textStyle
&& typedOther.color == color
&& typedOther.selectedColor == selectedColor && typedOther.selectedColor == selectedColor
&& typedOther.disabledColor == disabledColor && typedOther.disabledColor == disabledColor
&& typedOther.fillColor == fillColor && typedOther.fillColor == fillColor
...@@ -192,6 +205,7 @@ class ToggleButtonsThemeData extends Diagnosticable { ...@@ -192,6 +205,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
@override @override
void debugFillProperties(DiagnosticPropertiesBuilder properties) { void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties); super.debugFillProperties(properties);
textStyle?.debugFillProperties(properties, prefix: 'textStyle.');
properties.add(ColorProperty('color', color, defaultValue: null)); properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null)); properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null));
properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null)); properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null));
......
...@@ -250,6 +250,78 @@ void main() { ...@@ -250,6 +250,78 @@ void main() {
}, },
); );
testWidgets('Default text style is applied', (WidgetTester tester) async {
final ThemeData theme = ThemeData();
await tester.pumpWidget(
Material(
child: boilerplate(
child: ToggleButtons(
isSelected: const <bool>[false, true],
onPressed: (int index) {},
children: const <Widget>[
Text('First child'),
Text('Second child'),
],
),
),
),
);
TextStyle textStyle;
textStyle = tester.widget<DefaultTextStyle>(find.descendant(
of: find.widgetWithText(RawMaterialButton, 'First child'),
matching: find.byType(DefaultTextStyle),
)).style;
expect(textStyle.fontFamily, theme.textTheme.body1.fontFamily);
expect(textStyle.decoration, theme.textTheme.body1.decoration);
textStyle = tester.widget<DefaultTextStyle>(find.descendant(
of: find.widgetWithText(RawMaterialButton, 'Second child'),
matching: find.byType(DefaultTextStyle),
)).style;
expect(textStyle.fontFamily, theme.textTheme.body1.fontFamily);
expect(textStyle.decoration, theme.textTheme.body1.decoration);
});
testWidgets('Custom text style except color is applied', (WidgetTester tester) async {
await tester.pumpWidget(
Material(
child: boilerplate(
child: ToggleButtons(
isSelected: const <bool>[false, true],
onPressed: (int index) {},
textStyle: const TextStyle(
textBaseline: TextBaseline.ideographic,
fontSize: 20.0,
color: Colors.orange,
),
children: const <Widget>[
Text('First child'),
Text('Second child'),
],
),
),
),
);
TextStyle textStyle;
textStyle = tester.widget<DefaultTextStyle>(find.descendant(
of: find.widgetWithText(RawMaterialButton, 'First child'),
matching: find.byType(DefaultTextStyle),
)).style;
expect(textStyle.textBaseline, TextBaseline.ideographic);
expect(textStyle.fontSize, 20.0);
expect(textStyle.color, isNot(Colors.orange));
textStyle = tester.widget<DefaultTextStyle>(find.descendant(
of: find.widgetWithText(RawMaterialButton, 'Second child'),
matching: find.byType(DefaultTextStyle),
)).style;
expect(textStyle.textBaseline, TextBaseline.ideographic);
expect(textStyle.fontSize, 20.0);
expect(textStyle.color, isNot(Colors.orange));
});
testWidgets( testWidgets(
'Default text/icon colors for enabled, selected and disabled states', 'Default text/icon colors for enabled, selected and disabled states',
(WidgetTester tester) async { (WidgetTester tester) async {
......
...@@ -24,6 +24,7 @@ void main() { ...@@ -24,6 +24,7 @@ void main() {
test('ToggleButtonsThemeData defaults', () { test('ToggleButtonsThemeData defaults', () {
const ToggleButtonsThemeData themeData = ToggleButtonsThemeData(); const ToggleButtonsThemeData themeData = ToggleButtonsThemeData();
expect(themeData.textStyle, null);
expect(themeData.color, null); expect(themeData.color, null);
expect(themeData.selectedColor, null); expect(themeData.selectedColor, null);
expect(themeData.disabledColor, null); expect(themeData.disabledColor, null);
...@@ -39,6 +40,7 @@ void main() { ...@@ -39,6 +40,7 @@ void main() {
expect(themeData.borderWidth, null); expect(themeData.borderWidth, null);
const ToggleButtonsTheme theme = ToggleButtonsTheme(data: ToggleButtonsThemeData()); const ToggleButtonsTheme theme = ToggleButtonsTheme(data: ToggleButtonsThemeData());
expect(theme.data.textStyle, null);
expect(theme.data.color, null); expect(theme.data.color, null);
expect(theme.data.selectedColor, null); expect(theme.data.selectedColor, null);
expect(theme.data.disabledColor, null); expect(theme.data.disabledColor, null);
...@@ -69,6 +71,7 @@ void main() { ...@@ -69,6 +71,7 @@ void main() {
testWidgets('ToggleButtonsThemeData implements debugFillProperties', (WidgetTester tester) async { testWidgets('ToggleButtonsThemeData implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const ToggleButtonsThemeData( const ToggleButtonsThemeData(
textStyle: TextStyle(fontSize: 10),
color: Color(0xfffffff0), color: Color(0xfffffff0),
selectedColor: Color(0xfffffff1), selectedColor: Color(0xfffffff1),
disabledColor: Color(0xfffffff2), disabledColor: Color(0xfffffff2),
...@@ -90,6 +93,8 @@ void main() { ...@@ -90,6 +93,8 @@ void main() {
.toList(); .toList();
expect(description, <String>[ expect(description, <String>[
'textStyle.inherit: true',
'textStyle.size: 10.0',
'color: Color(0xfffffff0)', 'color: Color(0xfffffff0)',
'selectedColor: Color(0xfffffff1)', 'selectedColor: Color(0xfffffff1)',
'disabledColor: Color(0xfffffff2)', 'disabledColor: Color(0xfffffff2)',
...@@ -106,6 +111,49 @@ void main() { ...@@ -106,6 +111,49 @@ void main() {
]); ]);
}); });
testWidgets('Theme text style, except color, is applied', (WidgetTester tester) async {
await tester.pumpWidget(
Material(
child: boilerplate(
child: ToggleButtonsTheme(
data: const ToggleButtonsThemeData(
textStyle: TextStyle(
color: Colors.orange,
textBaseline: TextBaseline.ideographic,
fontSize: 20.0,
),
),
child: ToggleButtons(
isSelected: const <bool>[false, true],
onPressed: (int index) {},
children: const <Widget>[
Text('First child'),
Text('Second child'),
],
),
),
),
),
);
TextStyle textStyle;
textStyle = tester.widget<DefaultTextStyle>(find.descendant(
of: find.widgetWithText(RawMaterialButton, 'First child'),
matching: find.byType(DefaultTextStyle),
)).style;
expect(textStyle.textBaseline, TextBaseline.ideographic);
expect(textStyle.fontSize, 20.0);
expect(textStyle.color, isNot(Colors.orange));
textStyle = tester.widget<DefaultTextStyle>(find.descendant(
of: find.widgetWithText(RawMaterialButton, 'Second child'),
matching: find.byType(DefaultTextStyle),
)).style;
expect(textStyle.textBaseline, TextBaseline.ideographic);
expect(textStyle.fontSize, 20.0);
expect(textStyle.color, isNot(Colors.orange));
});
testWidgets( testWidgets(
'Theme text/icon colors for enabled, selected and disabled states', 'Theme text/icon colors for enabled, selected and disabled states',
(WidgetTester tester) async { (WidgetTester tester) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment