Unverified Commit 946a1291 authored by xubaolin's avatar xubaolin Committed by GitHub

Update [ToggleButtons] to support extend down/up vertically (#70670)

parent 60bdcf55
...@@ -15,9 +15,9 @@ import 'theme.dart'; ...@@ -15,9 +15,9 @@ import 'theme.dart';
import 'theme_data.dart'; import 'theme_data.dart';
import 'toggle_buttons_theme.dart'; import 'toggle_buttons_theme.dart';
/// A horizontal set of toggle buttons. /// A set of toggle buttons.
/// ///
/// The list of [children] are laid out in a row. The state of each button /// The list of [children] are laid out along [direction]. The state of each button
/// is controlled by [isSelected], which is a list of bools that determine /// is controlled by [isSelected], which is a list of bools that determine
/// if a button is in an unselected or selected state. They are both /// if a button is in an unselected or selected state. They are both
/// correlated by their index in the list. The length of [isSelected] has to /// correlated by their index in the list. The length of [isSelected] has to
...@@ -150,9 +150,9 @@ import 'toggle_buttons_theme.dart'; ...@@ -150,9 +150,9 @@ import 'toggle_buttons_theme.dart';
/// ///
/// * <https://material.io/design/components/buttons.html#toggle-button> /// * <https://material.io/design/components/buttons.html#toggle-button>
class ToggleButtons extends StatelessWidget { class ToggleButtons extends StatelessWidget {
/// Creates a horizontal set of toggle buttons. /// Creates a set of toggle buttons.
/// ///
/// It displays its widgets provided in a [List] of [children] horizontally. /// It displays its widgets provided in a [List] of [children] along [direction].
/// The state of each button is controlled by [isSelected], which is a list /// The state of each button is controlled by [isSelected], which is a list
/// of bools that determine if a button is in an active, disabled, or /// of bools that determine if a button is in an active, disabled, or
/// selected state. They are both correlated by their index in the list. /// selected state. They are both correlated by their index in the list.
...@@ -162,7 +162,8 @@ class ToggleButtons extends StatelessWidget { ...@@ -162,7 +162,8 @@ class ToggleButtons extends StatelessWidget {
/// Both [children] and [isSelected] properties arguments are required. /// Both [children] and [isSelected] properties arguments are required.
/// ///
/// [isSelected] values must be non-null. [focusNodes] must be null or a /// [isSelected] values must be non-null. [focusNodes] must be null or a
/// list of non-null nodes. [renderBorder] must not be null. /// list of non-null nodes. [renderBorder] and [direction] must not be null.
/// If [direction] is [Axis.vertical], [verticalDirection] must not be null.
const ToggleButtons({ const ToggleButtons({
Key? key, Key? key,
required this.children, required this.children,
...@@ -186,10 +187,14 @@ class ToggleButtons extends StatelessWidget { ...@@ -186,10 +187,14 @@ class ToggleButtons extends StatelessWidget {
this.disabledBorderColor, this.disabledBorderColor,
this.borderRadius, this.borderRadius,
this.borderWidth, this.borderWidth,
this.direction = Axis.horizontal,
this.verticalDirection = VerticalDirection.down,
}) : }) :
assert(children != null), assert(children != null),
assert(isSelected != null), assert(isSelected != null),
assert(children.length == isSelected.length), assert(children.length == isSelected.length),
assert(direction != null),
assert(direction == Axis.horizontal || verticalDirection != null),
super(key: key); super(key: key);
static const double _defaultBorderWidth = 1.0; static const double _defaultBorderWidth = 1.0;
...@@ -382,14 +387,31 @@ class ToggleButtons extends StatelessWidget { ...@@ -382,14 +387,31 @@ class ToggleButtons extends StatelessWidget {
/// the buttons default to non-rounded borders. /// the buttons default to non-rounded borders.
final BorderRadius? borderRadius; final BorderRadius? borderRadius;
bool _isFirstIndex(int index, int length, TextDirection textDirection) { /// The direction along which the buttons are rendered.
return index == 0 && textDirection == TextDirection.ltr ///
|| index == length - 1 && textDirection == TextDirection.rtl; /// Defaults to [Axis.horizontal].
final Axis direction;
/// If [direction] is [Axis.vertical], this parameter determines whether to lay out
/// the buttons starting from the first or last child from top to bottom.
final VerticalDirection verticalDirection;
// Determines if this is the first child that is being laid out
// by the render object, _not_ the order of the children in its list.
bool _isFirstButton(int index, int length, TextDirection textDirection) {
return index == 0 && ((direction == Axis.horizontal && textDirection == TextDirection.ltr) ||
(direction == Axis.vertical && verticalDirection == VerticalDirection.down))
|| index == length - 1 && ((direction == Axis.horizontal && textDirection == TextDirection.rtl) ||
(direction == Axis.vertical && verticalDirection == VerticalDirection.up));
} }
bool _isLastIndex(int index, int length, TextDirection textDirection) { // Determines if this is the last child that is being laid out
return index == length - 1 && textDirection == TextDirection.ltr // by the render object, _not_ the order of the children in its list.
|| index == 0 && textDirection == TextDirection.rtl; bool _isLastButton(int index, int length, TextDirection textDirection) {
return index == length - 1 && ((direction == Axis.horizontal && textDirection == TextDirection.ltr) ||
(direction == Axis.vertical && verticalDirection == VerticalDirection.down))
|| index == 0 && ((direction == Axis.horizontal && textDirection == TextDirection.rtl) ||
(direction == Axis.vertical && verticalDirection == VerticalDirection.up));
} }
BorderRadius _getEdgeBorderRadius( BorderRadius _getEdgeBorderRadius(
...@@ -402,17 +424,32 @@ class ToggleButtons extends StatelessWidget { ...@@ -402,17 +424,32 @@ class ToggleButtons extends StatelessWidget {
?? toggleButtonsTheme.borderRadius ?? toggleButtonsTheme.borderRadius
?? BorderRadius.zero; ?? BorderRadius.zero;
if (_isFirstIndex(index, length, textDirection)) { if (direction == Axis.horizontal) {
if (_isFirstButton(index, length, textDirection)) {
return BorderRadius.only( return BorderRadius.only(
topLeft: resultingBorderRadius.topLeft, topLeft: resultingBorderRadius.topLeft,
bottomLeft: resultingBorderRadius.bottomLeft, bottomLeft: resultingBorderRadius.bottomLeft,
); );
} else if (_isLastIndex(index, length, textDirection)) { } else if (_isLastButton(index, length, textDirection)) {
return BorderRadius.only( return BorderRadius.only(
topRight: resultingBorderRadius.topRight, topRight: resultingBorderRadius.topRight,
bottomRight: resultingBorderRadius.bottomRight, bottomRight: resultingBorderRadius.bottomRight,
); );
} }
} else {
if (_isFirstButton(index, length, textDirection)) {
return BorderRadius.only(
topLeft: resultingBorderRadius.topLeft,
topRight: resultingBorderRadius.topRight,
);
} else if (_isLastButton(index, length, textDirection)) {
return BorderRadius.only(
bottomLeft: resultingBorderRadius.bottomLeft,
bottomRight: resultingBorderRadius.bottomRight,
);
}
}
return BorderRadius.zero; return BorderRadius.zero;
} }
...@@ -429,17 +466,31 @@ class ToggleButtons extends StatelessWidget { ...@@ -429,17 +466,31 @@ class ToggleButtons extends StatelessWidget {
?? toggleButtonsTheme.borderWidth ?? toggleButtonsTheme.borderWidth
?? _defaultBorderWidth; ?? _defaultBorderWidth;
if (_isFirstIndex(index, length, textDirection)) { if (direction == Axis.horizontal) {
if (_isFirstButton(index, length, textDirection)) {
return BorderRadius.only( return BorderRadius.only(
topLeft: resultingBorderRadius.topLeft - Radius.circular(resultingBorderWidth / 2.0), topLeft: resultingBorderRadius.topLeft - Radius.circular(resultingBorderWidth / 2.0),
bottomLeft: resultingBorderRadius.bottomLeft - Radius.circular(resultingBorderWidth / 2.0), bottomLeft: resultingBorderRadius.bottomLeft - Radius.circular(resultingBorderWidth / 2.0),
); );
} else if (_isLastIndex(index, length, textDirection)) { } else if (_isLastButton(index, length, textDirection)) {
return BorderRadius.only( return BorderRadius.only(
topRight: resultingBorderRadius.topRight - Radius.circular(resultingBorderWidth / 2.0), topRight: resultingBorderRadius.topRight - Radius.circular(resultingBorderWidth / 2.0),
bottomRight: resultingBorderRadius.bottomRight - Radius.circular(resultingBorderWidth / 2.0), bottomRight: resultingBorderRadius.bottomRight - Radius.circular(resultingBorderWidth / 2.0),
); );
} }
} else {
if (_isFirstButton(index, length, textDirection)) {
return BorderRadius.only(
topLeft: resultingBorderRadius.topLeft - Radius.circular(resultingBorderWidth / 2.0),
topRight: resultingBorderRadius.topRight - Radius.circular(resultingBorderWidth / 2.0),
);
} else if (_isLastButton(index, length, textDirection)) {
return BorderRadius.only(
bottomLeft: resultingBorderRadius.bottomLeft - Radius.circular(resultingBorderWidth / 2.0),
bottomRight: resultingBorderRadius.bottomRight - Radius.circular(resultingBorderWidth / 2.0),
);
}
}
return BorderRadius.zero; return BorderRadius.zero;
} }
...@@ -478,7 +529,7 @@ class ToggleButtons extends StatelessWidget { ...@@ -478,7 +529,7 @@ class ToggleButtons extends StatelessWidget {
} }
} }
BorderSide _getHorizontalBorderSide( BorderSide _getBorderSide(
int index, int index,
ThemeData theme, ThemeData theme,
ToggleButtonsThemeData toggleButtonsTheme, ToggleButtonsThemeData toggleButtonsTheme,
...@@ -579,16 +630,12 @@ class ToggleButtons extends StatelessWidget { ...@@ -579,16 +630,12 @@ class ToggleButtons extends StatelessWidget {
final ToggleButtonsThemeData toggleButtonsTheme = ToggleButtonsTheme.of(context); final ToggleButtonsThemeData toggleButtonsTheme = ToggleButtonsTheme.of(context);
final TextDirection textDirection = Directionality.of(context); final TextDirection textDirection = Directionality.of(context);
return IntrinsicHeight( final List<Widget> buttons = List<Widget>.generate(children.length, (int index) {
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(children.length, (int index) {
final BorderRadius edgeBorderRadius = _getEdgeBorderRadius(index, children.length, textDirection, toggleButtonsTheme); final BorderRadius edgeBorderRadius = _getEdgeBorderRadius(index, children.length, textDirection, toggleButtonsTheme);
final BorderRadius clipBorderRadius = _getClipBorderRadius(index, children.length, textDirection, toggleButtonsTheme); final BorderRadius clipBorderRadius = _getClipBorderRadius(index, children.length, textDirection, toggleButtonsTheme);
final BorderSide leadingBorderSide = _getLeadingBorderSide(index, theme, toggleButtonsTheme); final BorderSide leadingBorderSide = _getLeadingBorderSide(index, theme, toggleButtonsTheme);
final BorderSide horizontalBorderSide = _getHorizontalBorderSide(index, theme, toggleButtonsTheme); final BorderSide borderSide = _getBorderSide(index, theme, toggleButtonsTheme);
final BorderSide trailingBorderSide = _getTrailingBorderSide(index, theme, toggleButtonsTheme); final BorderSide trailingBorderSide = _getTrailingBorderSide(index, theme, toggleButtonsTheme);
return _ToggleButton( return _ToggleButton(
...@@ -605,19 +652,36 @@ class ToggleButtons extends StatelessWidget { ...@@ -605,19 +652,36 @@ class ToggleButtons extends StatelessWidget {
splashColor: splashColor ?? toggleButtonsTheme.splashColor, splashColor: splashColor ?? toggleButtonsTheme.splashColor,
focusNode: focusNodes != null ? focusNodes![index] : null, focusNode: focusNodes != null ? focusNodes![index] : null,
onPressed: onPressed != null onPressed: onPressed != null
? () { onPressed!(index); } ? () {onPressed!(index);}
: null, : null,
mouseCursor: mouseCursor, mouseCursor: mouseCursor,
leadingBorderSide: leadingBorderSide, leadingBorderSide: leadingBorderSide,
horizontalBorderSide: horizontalBorderSide, borderSide: borderSide,
trailingBorderSide: trailingBorderSide, trailingBorderSide: trailingBorderSide,
borderRadius: edgeBorderRadius, borderRadius: edgeBorderRadius,
clipRadius: clipBorderRadius, clipRadius: clipBorderRadius,
isFirstButton: index == 0, isFirstButton: index == 0,
isLastButton: index == children.length - 1, isLastButton: index == children.length - 1,
direction: direction,
verticalDirection: verticalDirection,
child: children[index], child: children[index],
); );
}), });
return direction == Axis.horizontal
? IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: buttons,
),
)
: IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
verticalDirection: verticalDirection,
children: buttons,
), ),
); );
} }
...@@ -644,6 +708,8 @@ class ToggleButtons extends StatelessWidget { ...@@ -644,6 +708,8 @@ class ToggleButtons extends StatelessWidget {
properties.add(ColorProperty('disabledBorderColor', disabledBorderColor, defaultValue: null)); properties.add(ColorProperty('disabledBorderColor', disabledBorderColor, defaultValue: null));
properties.add(DiagnosticsProperty<BorderRadius>('borderRadius', borderRadius, defaultValue: null)); properties.add(DiagnosticsProperty<BorderRadius>('borderRadius', borderRadius, defaultValue: null));
properties.add(DoubleProperty('borderWidth', borderWidth, defaultValue: null)); properties.add(DoubleProperty('borderWidth', borderWidth, defaultValue: null));
properties.add(DiagnosticsProperty<Axis>('direction', direction, defaultValue: Axis.horizontal));
properties.add(DiagnosticsProperty<VerticalDirection>('verticalDirection', verticalDirection, defaultValue: VerticalDirection.down));
} }
} }
...@@ -676,12 +742,14 @@ class _ToggleButton extends StatelessWidget { ...@@ -676,12 +742,14 @@ class _ToggleButton extends StatelessWidget {
this.onPressed, this.onPressed,
this.mouseCursor, this.mouseCursor,
required this.leadingBorderSide, required this.leadingBorderSide,
required this.horizontalBorderSide, required this.borderSide,
required this.trailingBorderSide, required this.trailingBorderSide,
required this.borderRadius, required this.borderRadius,
required this.clipRadius, required this.clipRadius,
required this.isFirstButton, required this.isFirstButton,
required this.isLastButton, required this.isLastButton,
required this.direction,
required this.verticalDirection,
required this.child, required this.child,
}) : super(key: key); }) : super(key: key);
...@@ -740,8 +808,12 @@ class _ToggleButton extends StatelessWidget { ...@@ -740,8 +808,12 @@ class _ToggleButton extends StatelessWidget {
/// The width and color of the button's leading side border. /// The width and color of the button's leading side border.
final BorderSide leadingBorderSide; final BorderSide leadingBorderSide;
/// The width and color of the button's top and bottom side borders. /// If [direction] is [Axis.horizontal], this corresponds the width and color
final BorderSide horizontalBorderSide; /// of the button's top and bottom side borders.
///
/// If [direction] is [Axis.vertical], this corresponds the width and color
/// of the button's left and right side borders.
final BorderSide borderSide;
/// The width and color of the button's trailing side border. /// The width and color of the button's trailing side border.
final BorderSide trailingBorderSide; final BorderSide trailingBorderSide;
...@@ -761,6 +833,13 @@ class _ToggleButton extends StatelessWidget { ...@@ -761,6 +833,13 @@ class _ToggleButton extends StatelessWidget {
/// Whether or not this toggle button is the last button in the list. /// Whether or not this toggle button is the last button in the list.
final bool isLastButton; final bool isLastButton;
/// The direction along which the buttons are rendered.
final Axis direction;
/// If [direction] is [Axis.vertical], this property defines whether or not this button in its list
/// of buttons is laid out starting from top to bottom or from bottom to top.
final VerticalDirection verticalDirection;
/// The button's label, which is usually an [Icon] or a [Text] widget. /// The button's label, which is usually an [Icon] or a [Text] widget.
final Widget child; final Widget child;
...@@ -840,11 +919,13 @@ class _ToggleButton extends StatelessWidget { ...@@ -840,11 +919,13 @@ class _ToggleButton extends StatelessWidget {
return _SelectToggleButton( return _SelectToggleButton(
key: key, key: key,
leadingBorderSide: leadingBorderSide, leadingBorderSide: leadingBorderSide,
horizontalBorderSide: horizontalBorderSide, borderSide: borderSide,
trailingBorderSide: trailingBorderSide, trailingBorderSide: trailingBorderSide,
borderRadius: borderRadius, borderRadius: borderRadius,
isFirstButton: isFirstButton, isFirstButton: isFirstButton,
isLastButton: isLastButton, isLastButton: isLastButton,
direction: direction,
verticalDirection: verticalDirection,
child: result, child: result,
); );
} }
...@@ -865,11 +946,13 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget { ...@@ -865,11 +946,13 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget {
Key? key, Key? key,
required Widget child, required Widget child,
required this.leadingBorderSide, required this.leadingBorderSide,
required this.horizontalBorderSide, required this.borderSide,
required this.trailingBorderSide, required this.trailingBorderSide,
required this.borderRadius, required this.borderRadius,
required this.isFirstButton, required this.isFirstButton,
required this.isLastButton, required this.isLastButton,
required this.direction,
required this.verticalDirection,
}) : super( }) : super(
key: key, key: key,
child: child, child: child,
...@@ -878,8 +961,14 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget { ...@@ -878,8 +961,14 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget {
// The width and color of the button's leading side border. // The width and color of the button's leading side border.
final BorderSide leadingBorderSide; final BorderSide leadingBorderSide;
// The width and color of the button's top and bottom side borders. // The width and color of the side borders.
final BorderSide horizontalBorderSide; //
// If [direction] is [Axis.horizontal], this corresponds to the width and color
// of the button's top and bottom side borders.
//
// If [direction] is [Axis.vertical], this corresponds to the width and color
// of the button's left and right side borders.
final BorderSide borderSide;
// The width and color of the button's trailing side border. // The width and color of the button's trailing side border.
final BorderSide trailingBorderSide; final BorderSide trailingBorderSide;
...@@ -893,14 +982,23 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget { ...@@ -893,14 +982,23 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget {
// Whether or not this toggle button is the last button in the list. // Whether or not this toggle button is the last button in the list.
final bool isLastButton; final bool isLastButton;
// The direction along which the buttons are rendered.
final Axis direction;
// If [direction] is [Axis.vertical], this property defines whether or not this button in its list
// of buttons is laid out starting from top to bottom or from bottom to top.
final VerticalDirection verticalDirection;
@override @override
_SelectToggleButtonRenderObject createRenderObject(BuildContext context) => _SelectToggleButtonRenderObject( _SelectToggleButtonRenderObject createRenderObject(BuildContext context) => _SelectToggleButtonRenderObject(
leadingBorderSide, leadingBorderSide,
horizontalBorderSide, borderSide,
trailingBorderSide, trailingBorderSide,
borderRadius, borderRadius,
isFirstButton, isFirstButton,
isLastButton, isLastButton,
direction,
verticalDirection,
Directionality.of(context), Directionality.of(context),
); );
...@@ -908,11 +1006,13 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget { ...@@ -908,11 +1006,13 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget {
void updateRenderObject(BuildContext context, _SelectToggleButtonRenderObject renderObject) { void updateRenderObject(BuildContext context, _SelectToggleButtonRenderObject renderObject) {
renderObject renderObject
..leadingBorderSide = leadingBorderSide ..leadingBorderSide = leadingBorderSide
..horizontalBorderSide = horizontalBorderSide ..borderSide = borderSide
..trailingBorderSide = trailingBorderSide ..trailingBorderSide = trailingBorderSide
..borderRadius = borderRadius ..borderRadius = borderRadius
..isFirstButton = isFirstButton ..isFirstButton = isFirstButton
..isLastButton = isLastButton ..isLastButton = isLastButton
..direction = direction
..verticalDirection = verticalDirection
..textDirection = Directionality.of(context); ..textDirection = Directionality.of(context);
} }
} }
...@@ -920,15 +1020,35 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget { ...@@ -920,15 +1020,35 @@ class _SelectToggleButton extends SingleChildRenderObjectWidget {
class _SelectToggleButtonRenderObject extends RenderShiftedBox { class _SelectToggleButtonRenderObject extends RenderShiftedBox {
_SelectToggleButtonRenderObject( _SelectToggleButtonRenderObject(
this._leadingBorderSide, this._leadingBorderSide,
this._horizontalBorderSide, this._borderSide,
this._trailingBorderSide, this._trailingBorderSide,
this._borderRadius, this._borderRadius,
this._isFirstButton, this._isFirstButton,
this._isLastButton, this._isLastButton,
this._direction,
this._verticalDirection,
this._textDirection, [ this._textDirection, [
RenderBox? child, RenderBox? child,
]) : super(child); ]) : super(child);
Axis get direction => _direction;
Axis _direction;
set direction(Axis value) {
if (_direction == value)
return;
_direction = value;
markNeedsLayout();
}
VerticalDirection get verticalDirection => _verticalDirection;
VerticalDirection _verticalDirection;
set verticalDirection(VerticalDirection value) {
if (_verticalDirection == value)
return;
_verticalDirection = value;
markNeedsLayout();
}
// The width and color of the button's leading side border. // The width and color of the button's leading side border.
BorderSide get leadingBorderSide => _leadingBorderSide; BorderSide get leadingBorderSide => _leadingBorderSide;
BorderSide _leadingBorderSide; BorderSide _leadingBorderSide;
...@@ -940,12 +1060,12 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -940,12 +1060,12 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
} }
// The width and color of the button's top and bottom side borders. // The width and color of the button's top and bottom side borders.
BorderSide get horizontalBorderSide => _horizontalBorderSide; BorderSide get borderSide => _borderSide;
BorderSide _horizontalBorderSide; BorderSide _borderSide;
set horizontalBorderSide(BorderSide value) { set borderSide(BorderSide value) {
if (_horizontalBorderSide == value) if (_borderSide == value)
return; return;
_horizontalBorderSide = value; _borderSide = value;
markNeedsLayout(); markNeedsLayout();
} }
...@@ -1003,6 +1123,10 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1003,6 +1123,10 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
return box == null ? 0.0 : box.getMaxIntrinsicHeight(width); return box == null ? 0.0 : box.getMaxIntrinsicHeight(width);
} }
static double _minHeight(RenderBox? box, double width) {
return box == null ? 0.0 : box.getMinIntrinsicHeight(width);
}
static double _minWidth(RenderBox? box, double height) { static double _minWidth(RenderBox? box, double height) {
return box == null ? 0.0 : box.getMinIntrinsicWidth(height); return box == null ? 0.0 : box.getMinIntrinsicWidth(height);
} }
...@@ -1014,32 +1138,37 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1014,32 +1138,37 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
@override @override
double computeDistanceToActualBaseline(TextBaseline baseline) { double computeDistanceToActualBaseline(TextBaseline baseline) {
// The baseline of this widget is the baseline of its child // The baseline of this widget is the baseline of its child
return child!.computeDistanceToActualBaseline(baseline)! + return direction == Axis.horizontal
horizontalBorderSide.width; ? child!.computeDistanceToActualBaseline(baseline)! + borderSide.width
: child!.computeDistanceToActualBaseline(baseline)! + leadingBorderSide.width;
} }
@override @override
double computeMaxIntrinsicHeight(double width) { double computeMaxIntrinsicHeight(double width) {
return horizontalBorderSide.width + return direction == Axis.horizontal
_maxHeight(child, width) + ? borderSide.width * 2.0 + _maxHeight(child, width)
horizontalBorderSide.width; : leadingBorderSide.width + _maxHeight(child, width) + trailingBorderSide.width;
} }
@override @override
double computeMinIntrinsicHeight(double width) => computeMaxIntrinsicHeight(width); double computeMinIntrinsicHeight(double width) {
return direction == Axis.horizontal
? borderSide.width * 2.0 + _minHeight(child, width)
: leadingBorderSide.width + _maxHeight(child, width) + trailingBorderSide.width;
}
@override @override
double computeMaxIntrinsicWidth(double height) { double computeMaxIntrinsicWidth(double height) {
return leadingBorderSide.width + return direction == Axis.horizontal
_maxWidth(child, height) + ? leadingBorderSide.width + _maxWidth(child, height) + trailingBorderSide.width
trailingBorderSide.width; : borderSide.width * 2.0 + _maxWidth(child, height);
} }
@override @override
double computeMinIntrinsicWidth(double height) { double computeMinIntrinsicWidth(double height) {
return leadingBorderSide.width + return direction == Axis.horizontal
_minWidth(child, height) + ? leadingBorderSide.width + _minWidth(child, height) + trailingBorderSide.width
trailingBorderSide.width; : borderSide.width * 2.0 + _minWidth(child, height);
} }
@override @override
...@@ -1059,85 +1188,85 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1059,85 +1188,85 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
if (child == null) { if (child == null) {
return; return;
} }
final BoxParentData childParentData = child!.parentData! as BoxParentData;
if (direction == Axis.horizontal) {
switch (textDirection) { switch (textDirection) {
case TextDirection.ltr: case TextDirection.ltr:
final BoxParentData childParentData = child!.parentData! as BoxParentData; childParentData.offset = Offset(leadingBorderSide.width, borderSide.width);
childParentData.offset = Offset(leadingBorderSide.width, leadingBorderSide.width);
break; break;
case TextDirection.rtl: case TextDirection.rtl:
final BoxParentData childParentData = child!.parentData! as BoxParentData; childParentData.offset = Offset(trailingBorderSide.width, borderSide.width);
if (isLastButton) { break;
childParentData.offset = Offset(_trailingBorderOffset, _trailingBorderOffset);
} else {
childParentData.offset = Offset(0, horizontalBorderSide.width);
} }
} else {
switch (verticalDirection) {
case VerticalDirection.down:
childParentData.offset = Offset(borderSide.width, leadingBorderSide.width);
break;
case VerticalDirection.up:
childParentData.offset = Offset(borderSide.width, trailingBorderSide.width);
break; break;
} }
} }
}
double get _trailingBorderOffset => isLastButton ? trailingBorderSide.width : 0.0;
Size _computeSize({required BoxConstraints constraints, required ChildLayouter layoutChild}) { Size _computeSize({required BoxConstraints constraints, required ChildLayouter layoutChild}) {
if (child == null) { if (child == null) {
if (direction == Axis.horizontal) {
return constraints.constrain(Size(
leadingBorderSide.width + trailingBorderSide.width,
borderSide.width * 2.0,
));
} else {
return constraints.constrain(Size( return constraints.constrain(Size(
borderSide.width * 2.0,
leadingBorderSide.width + trailingBorderSide.width, leadingBorderSide.width + trailingBorderSide.width,
horizontalBorderSide.width * 2.0,
)); ));
} }
}
final double leftConstraint; final double leftConstraint;
final double rightConstraint; final double rightConstraint;
final double topConstraint;
switch (textDirection) { final double bottomConstraint;
case TextDirection.ltr:
rightConstraint = _trailingBorderOffset; // It does not matter what [textDirection] or [verticalDirection] is,
// since deflating the size constraints horizontally/vertically
// and the returned size accounts for the width of both sides.
if (direction == Axis.horizontal) {
rightConstraint = trailingBorderSide.width;
leftConstraint = leadingBorderSide.width; leftConstraint = leadingBorderSide.width;
topConstraint = borderSide.width;
final BoxConstraints innerConstraints = constraints.deflate( bottomConstraint = borderSide.width;
EdgeInsets.only( } else {
left: leftConstraint, rightConstraint = borderSide.width;
top: horizontalBorderSide.width, leftConstraint = borderSide.width;
right: rightConstraint, topConstraint = leadingBorderSide.width;
bottom: horizontalBorderSide.width, bottomConstraint = trailingBorderSide.width;
), }
);
final Size childSize = layoutChild(child!, innerConstraints);
return constraints.constrain(Size(
leftConstraint + childSize.width + rightConstraint,
horizontalBorderSide.width * 2.0 + childSize.height,
));
case TextDirection.rtl:
rightConstraint = leadingBorderSide.width;
leftConstraint = _trailingBorderOffset;
final BoxConstraints innerConstraints = constraints.deflate( final BoxConstraints innerConstraints = constraints.deflate(
EdgeInsets.only( EdgeInsets.only(
left: leftConstraint, left: leftConstraint,
top: horizontalBorderSide.width, top: topConstraint,
right: rightConstraint, right: rightConstraint,
bottom: horizontalBorderSide.width, bottom: bottomConstraint,
), ),
); );
final Size childSize = layoutChild(child!, innerConstraints); final Size childSize = layoutChild(child!, innerConstraints);
return constraints.constrain(Size( return constraints.constrain(Size(
leftConstraint + childSize.width + rightConstraint, leftConstraint + childSize.width + rightConstraint,
horizontalBorderSide.width * 2.0 + childSize.height, topConstraint + childSize.height + bottomConstraint,
)); ));
} }
}
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
super.paint(context, offset); super.paint(context, offset);
final Offset bottomRight = size.bottomRight(offset); final Offset bottomRight = size.bottomRight(offset);
final Rect outer = Rect.fromLTRB(offset.dx, offset.dy, bottomRight.dx, bottomRight.dy); final Rect outer = Rect.fromLTRB(offset.dx, offset.dy, bottomRight.dx, bottomRight.dy);
final Rect center = outer.deflate(horizontalBorderSide.width / 2.0); final Rect center = outer.deflate(borderSide.width / 2.0);
const double sweepAngle = math.pi / 2.0; const double sweepAngle = math.pi / 2.0;
final RRect rrect = RRect.fromRectAndCorners( final RRect rrect = RRect.fromRectAndCorners(
center, center,
topLeft: borderRadius.topLeft, topLeft: borderRadius.topLeft,
...@@ -1145,7 +1274,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1145,7 +1274,6 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
bottomLeft: borderRadius.bottomLeft, bottomLeft: borderRadius.bottomLeft,
bottomRight: borderRadius.bottomRight, bottomRight: borderRadius.bottomRight,
).scaleRadii(); ).scaleRadii();
final Rect tlCorner = Rect.fromLTWH( final Rect tlCorner = Rect.fromLTWH(
rrect.left, rrect.left,
rrect.top, rrect.top,
...@@ -1171,27 +1299,28 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1171,27 +1299,28 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
rrect.brRadiusY * 2, rrect.brRadiusY * 2,
); );
if (direction == Axis.horizontal) {
final Paint leadingPaint = leadingBorderSide.toPaint(); final Paint leadingPaint = leadingBorderSide.toPaint();
switch (textDirection) { switch (textDirection) {
case TextDirection.ltr: case TextDirection.ltr:
if (isLastButton) { if (isLastButton) {
final Path leftPath = Path() final Path leftPath = Path();
..moveTo(rrect.left, rrect.bottom + leadingBorderSide.width / 2) leftPath..moveTo(rrect.left, rrect.bottom + leadingBorderSide.width / 2)
..lineTo(rrect.left, rrect.top - leadingBorderSide.width / 2); ..lineTo(rrect.left, rrect.top - leadingBorderSide.width / 2);
context.canvas.drawPath(leftPath, leadingPaint); context.canvas.drawPath(leftPath, leadingPaint);
final Paint endingPaint = trailingBorderSide.toPaint(); final Paint endingPaint = trailingBorderSide.toPaint();
final Path endingPath = Path() final Path endingPath = Path();
..moveTo(rrect.left + horizontalBorderSide.width / 2.0, rrect.top) endingPath..moveTo(rrect.left + borderSide.width / 2.0, rrect.top)
..lineTo(rrect.right - rrect.trRadiusX, rrect.top) ..lineTo(rrect.right - rrect.trRadiusX, rrect.top)
..addArc(trCorner, math.pi * 3.0 / 2.0, sweepAngle) ..addArc(trCorner, math.pi * 3.0 / 2.0, sweepAngle)
..lineTo(rrect.right, rrect.bottom - rrect.brRadiusY) ..lineTo(rrect.right, rrect.bottom - rrect.brRadiusY)
..addArc(brCorner, 0, sweepAngle) ..addArc(brCorner, 0, sweepAngle)
..lineTo(rrect.left + horizontalBorderSide.width / 2.0, rrect.bottom); ..lineTo(rrect.left + borderSide.width / 2.0, rrect.bottom);
context.canvas.drawPath(endingPath, endingPaint); context.canvas.drawPath(endingPath, endingPaint);
} else if (isFirstButton) { } else if (isFirstButton) {
final Path leadingPath = Path() final Path leadingPath = Path();
..moveTo(outer.right, rrect.bottom) leadingPath..moveTo(outer.right, rrect.bottom)
..lineTo(rrect.left + rrect.blRadiusX, rrect.bottom) ..lineTo(rrect.left + rrect.blRadiusX, rrect.bottom)
..addArc(blCorner, math.pi / 2.0, sweepAngle) ..addArc(blCorner, math.pi / 2.0, sweepAngle)
..lineTo(rrect.left, rrect.top + rrect.tlRadiusY) ..lineTo(rrect.left, rrect.top + rrect.tlRadiusY)
...@@ -1199,39 +1328,40 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1199,39 +1328,40 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
..lineTo(outer.right, rrect.top); ..lineTo(outer.right, rrect.top);
context.canvas.drawPath(leadingPath, leadingPaint); context.canvas.drawPath(leadingPath, leadingPaint);
} else { } else {
final Path leadingPath = Path() final Path leadingPath = Path();
..moveTo(rrect.left, rrect.bottom + leadingBorderSide.width / 2) leadingPath..moveTo(rrect.left, rrect.bottom + leadingBorderSide.width / 2)
..lineTo(rrect.left, rrect.top - leadingBorderSide.width / 2); ..lineTo(rrect.left, rrect.top - leadingBorderSide.width / 2);
context.canvas.drawPath(leadingPath, leadingPaint); context.canvas.drawPath(leadingPath, leadingPaint);
final Paint horizontalPaint = horizontalBorderSide.toPaint(); final Paint horizontalPaint = borderSide.toPaint();
final Path horizontalPaths = Path() final Path horizontalPaths = Path();
..moveTo(rrect.left + horizontalBorderSide.width / 2.0, rrect.top) horizontalPaths..moveTo(rrect.left + borderSide.width / 2.0, rrect.top)
..lineTo(outer.right - rrect.trRadiusX, rrect.top) ..lineTo(outer.right - rrect.trRadiusX, rrect.top)
..moveTo(rrect.left + horizontalBorderSide.width / 2.0 + rrect.tlRadiusX, rrect.bottom) ..moveTo(rrect.left + borderSide.width / 2.0 + rrect.tlRadiusX, rrect.bottom)
..lineTo(outer.right - rrect.trRadiusX, rrect.bottom); ..lineTo(outer.right - rrect.trRadiusX, rrect.bottom);
context.canvas.drawPath(horizontalPaths, horizontalPaint); context.canvas.drawPath(horizontalPaths, horizontalPaint);
} }
break; break;
case TextDirection.rtl: case TextDirection.rtl:
if (isLastButton) { if (isLastButton) {
final Path leadingPath = Path() final Path leadingPath = Path();
..moveTo(rrect.right, rrect.bottom + leadingBorderSide.width / 2) leadingPath..moveTo(rrect.right, rrect.bottom + leadingBorderSide.width / 2)
..lineTo(rrect.right, rrect.top - leadingBorderSide.width / 2); ..lineTo(rrect.right, rrect.top - leadingBorderSide.width / 2);
context.canvas.drawPath(leadingPath, leadingPaint); context.canvas.drawPath(leadingPath, leadingPaint);
final Paint endingPaint = trailingBorderSide.toPaint(); final Paint endingPaint = trailingBorderSide.toPaint();
final Path endingPath = Path() final Path endingPath = Path();
..moveTo(rrect.right - horizontalBorderSide.width / 2.0, rrect.top) endingPath..moveTo(rrect.right - borderSide.width / 2.0, rrect.top)
..lineTo(rrect.left + rrect.tlRadiusX, rrect.top) ..lineTo(rrect.left + rrect.tlRadiusX, rrect.top)
..addArc(tlCorner, math.pi * 3.0 / 2.0, -sweepAngle) ..addArc(tlCorner, math.pi * 3.0 / 2.0, -sweepAngle)
..lineTo(rrect.left, rrect.bottom - rrect.blRadiusY) ..lineTo(rrect.left, rrect.bottom - rrect.blRadiusY)
..addArc(blCorner, math.pi, -sweepAngle) ..addArc(blCorner, math.pi, -sweepAngle)
..lineTo(rrect.right - horizontalBorderSide.width / 2.0, rrect.bottom); ..lineTo(rrect.right - borderSide.width / 2.0, rrect.bottom);
context.canvas.drawPath(endingPath, endingPaint); context.canvas.drawPath(endingPath, endingPaint);
} else if (isFirstButton) { } else if (isFirstButton) {
final Path leadingPath = Path() final Path leadingPath = Path();
..moveTo(outer.left, rrect.bottom) leadingPath..moveTo(outer.left, rrect.bottom)
..lineTo(rrect.right - rrect.brRadiusX, rrect.bottom) ..lineTo(rrect.right - rrect.brRadiusX, rrect.bottom)
..addArc(brCorner, math.pi / 2.0, -sweepAngle) ..addArc(brCorner, math.pi / 2.0, -sweepAngle)
..lineTo(rrect.right, rrect.top + rrect.trRadiusY) ..lineTo(rrect.right, rrect.top + rrect.trRadiusY)
...@@ -1239,20 +1369,109 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox { ...@@ -1239,20 +1369,109 @@ class _SelectToggleButtonRenderObject extends RenderShiftedBox {
..lineTo(outer.left, rrect.top); ..lineTo(outer.left, rrect.top);
context.canvas.drawPath(leadingPath, leadingPaint); context.canvas.drawPath(leadingPath, leadingPaint);
} else { } else {
final Path leadingPath = Path() final Path leadingPath = Path();
..moveTo(rrect.right, rrect.bottom + leadingBorderSide.width / 2) leadingPath..moveTo(rrect.right, rrect.bottom + leadingBorderSide.width / 2)
..lineTo(rrect.right, rrect.top - leadingBorderSide.width / 2); ..lineTo(rrect.right, rrect.top - leadingBorderSide.width / 2);
context.canvas.drawPath(leadingPath, leadingPaint); context.canvas.drawPath(leadingPath, leadingPaint);
final Paint horizontalPaint = horizontalBorderSide.toPaint(); final Paint horizontalPaint = borderSide.toPaint();
final Path horizontalPaths = Path() final Path horizontalPaths = Path();
..moveTo(rrect.right - horizontalBorderSide.width / 2.0, rrect.top) horizontalPaths..moveTo(rrect.right - borderSide.width / 2.0, rrect.top)
..lineTo(outer.left - rrect.tlRadiusX, rrect.top) ..lineTo(outer.left - rrect.tlRadiusX, rrect.top)
..moveTo(rrect.right - horizontalBorderSide.width / 2.0 + rrect.trRadiusX, rrect.bottom) ..moveTo(rrect.right - borderSide.width / 2.0 + rrect.trRadiusX, rrect.bottom)
..lineTo(outer.left - rrect.tlRadiusX, rrect.bottom); ..lineTo(outer.left - rrect.tlRadiusX, rrect.bottom);
context.canvas.drawPath(horizontalPaths, horizontalPaint); context.canvas.drawPath(horizontalPaths, horizontalPaint);
} }
break; break;
} }
} else {
final Paint leadingPaint = leadingBorderSide.toPaint();
switch (verticalDirection) {
case VerticalDirection.down:
if (isLastButton) {
final Path topPath = Path();
topPath..moveTo(outer.left, outer.top + leadingBorderSide.width / 2)
..lineTo(outer.right, outer.top + leadingBorderSide.width / 2);
context.canvas.drawPath(topPath, leadingPaint);
final Paint endingPaint = trailingBorderSide.toPaint();
final Path endingPath = Path();
endingPath..moveTo(rrect.left, rrect.top + leadingBorderSide.width / 2.0)
..lineTo(rrect.left, rrect.bottom - rrect.blRadiusY)
..addArc(blCorner, math.pi * 3.0, -sweepAngle)
..lineTo(rrect.right - rrect.blRadiusX, rrect.bottom)
..addArc(brCorner, math.pi / 2.0, -sweepAngle)
..lineTo(rrect.right, rrect.top + leadingBorderSide.width / 2.0);
context.canvas.drawPath(endingPath, endingPaint);
} else if (isFirstButton) {
final Path leadingPath = Path();
leadingPath..moveTo(rrect.left, outer.bottom)
..lineTo(rrect.left, rrect.top + rrect.tlRadiusX)
..addArc(tlCorner, math.pi, sweepAngle)
..lineTo(rrect.right - rrect.trRadiusX, rrect.top)
..addArc(trCorner, math.pi * 3.0 / 2.0, sweepAngle)
..lineTo(rrect.right, outer.bottom);
context.canvas.drawPath(leadingPath, leadingPaint);
} else {
final Path topPath = Path();
topPath..moveTo(outer.left, outer.top + leadingBorderSide.width / 2)
..lineTo(outer.right, outer.top + leadingBorderSide.width / 2);
context.canvas.drawPath(topPath, leadingPaint);
final Paint paint = borderSide.toPaint();
final Path paths = Path(); // Left and right borders.
paths..moveTo(rrect.left, outer.top + leadingBorderSide.width)
..lineTo(rrect.left, outer.bottom)
..moveTo(rrect.right, outer.top + leadingBorderSide.width)
..lineTo(rrect.right, outer.bottom);
context.canvas.drawPath(paths, paint);
}
break;
case VerticalDirection.up:
if (isLastButton) {
final Path bottomPath = Path();
bottomPath..moveTo(outer.left, outer.bottom - leadingBorderSide.width / 2.0)
..lineTo(outer.right, outer.bottom - leadingBorderSide.width / 2.0);
context.canvas.drawPath(bottomPath, leadingPaint);
final Paint endingPaint = trailingBorderSide.toPaint();
final Path endingPath = Path();
endingPath..moveTo(rrect.left, rrect.bottom - leadingBorderSide.width / 2.0)
..lineTo(rrect.left, rrect.top + rrect.tlRadiusY)
..addArc(tlCorner, math.pi, sweepAngle)
..lineTo(rrect.right - rrect.trRadiusX, rrect.top)
..addArc(trCorner, math.pi * 3.0 / 2.0, sweepAngle)
..lineTo(rrect.right, rrect.bottom - leadingBorderSide.width / 2.0);
context.canvas.drawPath(endingPath, endingPaint);
} else if (isFirstButton) {
final Path leadingPath = Path();
leadingPath..moveTo(rrect.left, outer.top)
..lineTo(rrect.left, rrect.bottom - rrect.blRadiusY)
..addArc(blCorner, math.pi, -sweepAngle)
..lineTo(rrect.right - rrect.brRadiusX, rrect.bottom)
..addArc(brCorner, math.pi / 2.0, -sweepAngle)
..lineTo(rrect.right, outer.top);
context.canvas.drawPath(leadingPath, leadingPaint);
} else {
final Path bottomPath = Path();
bottomPath..moveTo(outer.left, outer.bottom - leadingBorderSide.width / 2.0)
..lineTo(outer.right, outer.bottom - leadingBorderSide.width / 2.0);
context.canvas.drawPath(bottomPath, leadingPaint);
final Paint paint = borderSide.toPaint();
final Path paths = Path(); // Left and right borders.
paths..moveTo(rrect.left, outer.top)
..lineTo(rrect.left, outer.bottom - leadingBorderSide.width)
..moveTo(rrect.right, outer.top)
..lineTo(rrect.right, outer.bottom - leadingBorderSide.width);
context.canvas.drawPath(paths, paint);
}
break;
}
}
} }
} }
...@@ -1398,6 +1398,156 @@ void main() { ...@@ -1398,6 +1398,156 @@ void main() {
}, },
); );
testWidgets(
'Properly draws borders based on state when direction is vertical and verticalDirection is down.',
(WidgetTester tester) async {
final ThemeData theme = ThemeData();
await tester.pumpWidget(
Material(
child: boilerplate(
child: ToggleButtons(
direction: Axis.vertical,
verticalDirection: VerticalDirection.down,
isSelected: const <bool>[false, true, false],
onPressed: (int index) {},
children: const <Widget>[
Text('First child'),
Text('Second child'),
Text('Third child'),
],
),
),
),
);
// The children should be laid out along vertical and the first child at top.
// The item height is icon height + default border width (48.0 + 1.0) pixels.
expect(tester.getCenter(find.text('First child')), const Offset(400.0, 251.0));
expect(tester.getCenter(find.text('Second child')), const Offset(400.0, 300.0));
expect(tester.getCenter(find.text('Third child')), const Offset(400.0, 349.0));
final List<RenderObject> toggleButtonRenderObject = tester.allRenderObjects.where((RenderObject object) {
return object.runtimeType.toString() == '_SelectToggleButtonRenderObject';
}).toSet().toList();
// The first button paints the left, top and right sides with a path.
expect(
toggleButtonRenderObject[0],
paints
// left side, top and right - enabled.
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: _defaultBorderWidth,
),
);
// The middle buttons paint a top side path first, followed by a
// left and right side path.
expect(
toggleButtonRenderObject[1],
paints
// top side - selected.
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: _defaultBorderWidth,
)
// left and right - selected.
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: _defaultBorderWidth,
),
);
// The last button paints a top side path first, followed by
// a left, bottom and right side path
expect(
toggleButtonRenderObject[2],
paints
// top side - selected, since previous button is selected.
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: _defaultBorderWidth,
)
// left side, bottom and right - enabled.
..path(
style: PaintingStyle.stroke,
color: theme.colorScheme.onSurface.withOpacity(0.12),
strokeWidth: _defaultBorderWidth,
),
);
},
);
testWidgets(
'VerticalDirection test when direction is vertical.',
(WidgetTester tester) async {
await tester.pumpWidget(
Material(
child: boilerplate(
child: ToggleButtons(
direction: Axis.vertical,
verticalDirection: VerticalDirection.up,
isSelected: const <bool>[false, true, false],
onPressed: (int index) {},
children: const <Widget>[
Text('First child'),
Text('Second child'),
Text('Third child'),
],
),
),
),
);
// The children should be laid out along vertical and the last child at top.
expect(tester.getCenter(find.text('Third child')), const Offset(400.0, 251.0));
expect(tester.getCenter(find.text('Second child')), const Offset(400.0, 300.0));
expect(tester.getCenter(find.text('First child')), const Offset(400.0, 349.0));
},
);
testWidgets('ToggleButtons implements debugFillProperties', (WidgetTester tester) async {
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
ToggleButtons(
direction: Axis.vertical,
verticalDirection: VerticalDirection.up,
borderWidth: 3.0,
color: Colors.green,
selectedBorderColor: Colors.pink,
disabledColor: Colors.blue,
disabledBorderColor: Colors.yellow,
borderRadius: const BorderRadius.all(Radius.circular(7.0)),
isSelected: const <bool>[false, true, false],
onPressed: (int index) {},
children: const <Widget>[
Text('First child'),
Text('Second child'),
Text('Third child'),
],
).debugFillProperties(builder);
final List<String> description = builder.properties
.where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
.map((DiagnosticsNode node) => node.toString()).toList();
expect(description, <String>[
'Buttons are enabled',
'color: MaterialColor(primary value: Color(0xff4caf50))',
'disabledColor: MaterialColor(primary value: Color(0xff2196f3))',
'selectedBorderColor: MaterialColor(primary value: Color(0xffe91e63))',
'disabledBorderColor: MaterialColor(primary value: Color(0xffffeb3b))',
'borderRadius: BorderRadius.circular(7.0)',
'borderWidth: 3.0',
'direction: Axis.vertical',
'verticalDirection: VerticalDirection.up'
]);
});
testWidgets('ToggleButtons changes mouse cursor when the button is hovered', (WidgetTester tester) async { testWidgets('ToggleButtons changes mouse cursor when the button is hovered', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
Material( Material(
......
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