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 {
@required this.children,
@required this.isSelected,
this.onPressed,
this.textStyle,
this.color,
this.selectedColor,
this.disabledColor,
......@@ -215,6 +216,13 @@ class ToggleButtons extends StatelessWidget {
/// When the callback is null, all toggle buttons will be disabled.
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
/// enabled and not selected.
///
......@@ -569,6 +577,7 @@ class ToggleButtons extends StatelessWidget {
return _ToggleButton(
selected: isSelected[index],
textStyle: textStyle,
color: color,
selectedColor: selectedColor,
disabledColor: disabledColor,
......@@ -603,6 +612,7 @@ class ToggleButtons extends StatelessWidget {
ifTrue: 'Buttons are disabled',
ifFalse: 'Buttons are enabled',
));
textStyle?.debugFillProperties(properties, prefix: 'textStyle.');
properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null));
properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null));
......@@ -634,6 +644,7 @@ class _ToggleButton extends StatelessWidget {
const _ToggleButton({
Key key,
this.selected = false,
this.textStyle,
this.color,
this.selectedColor,
this.disabledColor,
......@@ -657,6 +668,9 @@ class _ToggleButton extends StatelessWidget {
/// Determines if the button is displayed as active/selected or enabled.
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.
///
/// If [selected] is false and [onPressed] is not null, this color will be used.
......@@ -769,10 +783,12 @@ class _ToggleButton extends StatelessWidget {
currentFillColor = theme.colorScheme.surface.withOpacity(0.0);
}
final TextStyle currentTextStyle = textStyle ?? toggleButtonsTheme.textStyle ?? theme.textTheme.body1;
final Widget result = ClipRRect(
borderRadius: clipRadius,
child: RawMaterialButton(
textStyle: TextStyle(
textStyle: currentTextStyle.copyWith(
color: currentColor,
),
elevation: 0.0,
......
......@@ -28,6 +28,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
/// Creates the set of color and border properties used to configure
/// [ToggleButtons].
const ToggleButtonsThemeData({
this.textStyle,
this.color,
this.selectedColor,
this.disabledColor,
......@@ -43,6 +44,13 @@ class ToggleButtonsThemeData extends Diagnosticable {
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
/// is enabled.
final Color color;
......@@ -95,6 +103,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
ToggleButtonsThemeData copyWith({
TextStyle textStyle,
Color color,
Color selectedColor,
Color disabledColor,
......@@ -110,6 +119,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
double borderWidth,
}) {
return ToggleButtonsThemeData(
textStyle: textStyle ?? this.textStyle,
color: color ?? this.color,
selectedColor: selectedColor ?? this.selectedColor,
disabledColor: disabledColor ?? this.disabledColor,
......@@ -132,6 +142,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
if (a == null && b == null)
return null;
return ToggleButtonsThemeData(
textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, 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),
......@@ -151,6 +162,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
@override
int get hashCode {
return hashValues(
textStyle,
color,
selectedColor,
disabledColor,
......@@ -174,7 +186,8 @@ class ToggleButtonsThemeData extends Diagnosticable {
if (other.runtimeType != runtimeType)
return false;
final ToggleButtonsThemeData typedOther = other;
return typedOther.color == color
return typedOther.textStyle == textStyle
&& typedOther.color == color
&& typedOther.selectedColor == selectedColor
&& typedOther.disabledColor == disabledColor
&& typedOther.fillColor == fillColor
......@@ -192,6 +205,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
textStyle?.debugFillProperties(properties, prefix: 'textStyle.');
properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(ColorProperty('selectedColor', selectedColor, defaultValue: null));
properties.add(ColorProperty('disabledColor', disabledColor, defaultValue: null));
......
......@@ -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(
'Default text/icon colors for enabled, selected and disabled states',
(WidgetTester tester) async {
......
......@@ -24,6 +24,7 @@ void main() {
test('ToggleButtonsThemeData defaults', () {
const ToggleButtonsThemeData themeData = ToggleButtonsThemeData();
expect(themeData.textStyle, null);
expect(themeData.color, null);
expect(themeData.selectedColor, null);
expect(themeData.disabledColor, null);
......@@ -39,6 +40,7 @@ void main() {
expect(themeData.borderWidth, null);
const ToggleButtonsTheme theme = ToggleButtonsTheme(data: ToggleButtonsThemeData());
expect(theme.data.textStyle, null);
expect(theme.data.color, null);
expect(theme.data.selectedColor, null);
expect(theme.data.disabledColor, null);
......@@ -69,6 +71,7 @@ void main() {
testWidgets('ToggleButtonsThemeData implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
const ToggleButtonsThemeData(
textStyle: TextStyle(fontSize: 10),
color: Color(0xfffffff0),
selectedColor: Color(0xfffffff1),
disabledColor: Color(0xfffffff2),
......@@ -90,6 +93,8 @@ void main() {
.toList();
expect(description, <String>[
'textStyle.inherit: true',
'textStyle.size: 10.0',
'color: Color(0xfffffff0)',
'selectedColor: Color(0xfffffff1)',
'disabledColor: Color(0xfffffff2)',
......@@ -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(
'Theme text/icon colors for enabled, selected and disabled states',
(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