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
This commit is contained in:
Shi-Hao Hong 2019-09-13 08:19:06 -07:00 committed by GitHub
parent a7cfdbd3f3
commit 2bd7f9ff7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 199 additions and 0 deletions

View file

@ -9,6 +9,7 @@ import 'package:flutter/rendering.dart';
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 @@ class ToggleButtons extends StatelessWidget {
@required this.isSelected,
this.onPressed,
this.textStyle,
this.constraints,
this.color,
this.selectedColor,
this.disabledColor,
@ -223,6 +225,14 @@ class ToggleButtons extends StatelessWidget {
/// 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 @@ class ToggleButtons extends StatelessWidget {
return _ToggleButton(
selected: isSelected[index],
textStyle: textStyle,
constraints: constraints,
color: color,
selectedColor: selectedColor,
disabledColor: disabledColor,
@ -645,6 +656,7 @@ class _ToggleButton extends StatelessWidget {
Key key,
this.selected = false,
this.textStyle,
this.constraints,
this.color,
this.selectedColor,
this.disabledColor,
@ -671,6 +683,11 @@ class _ToggleButton extends StatelessWidget {
/// 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 @@ class _ToggleButton extends StatelessWidget {
}
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 @@ class _ToggleButton extends StatelessWidget {
textStyle: currentTextStyle.copyWith(
color: currentColor,
),
constraints: currentConstraints,
elevation: 0.0,
highlightElevation: 0.0,
fillColor: currentFillColor,

View file

@ -29,6 +29,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
/// [ToggleButtons].
const ToggleButtonsThemeData({
this.textStyle,
this.constraints,
this.color,
this.selectedColor,
this.disabledColor,
@ -51,6 +52,11 @@ class ToggleButtonsThemeData extends Diagnosticable {
/// 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 @@ class ToggleButtonsThemeData extends Diagnosticable {
/// new values.
ToggleButtonsThemeData copyWith({
TextStyle textStyle,
BoxConstraints constraints,
Color color,
Color selectedColor,
Color disabledColor,
@ -120,6 +127,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
}) {
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 @@ class ToggleButtonsThemeData extends Diagnosticable {
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 @@ class ToggleButtonsThemeData extends Diagnosticable {
int get hashCode {
return hashValues(
textStyle,
constraints,
color,
selectedColor,
disabledColor,
@ -187,6 +197,7 @@ class ToggleButtonsThemeData extends Diagnosticable {
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 @@ class ToggleButtonsThemeData extends Diagnosticable {
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));

View file

@ -309,6 +309,98 @@ void main() {
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 {

View file

@ -25,6 +25,7 @@ void main() {
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 @@ void main() {
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 @@ void main() {
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 @@ void main() {
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 @@ void main() {
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 {