Unverified Commit e74b9b5b authored by hangyu's avatar hangyu Committed by GitHub

Migrate InputDecorator to Material 3 (#107943)

* Support material 3 in inputDecorator

* Format polish

* format polish

* update input_decorator_test

* revert pub

* style update

* style polish

* default before base

* resolve comments

* Update text_field.2.dart

* move text styles into M2 theme

* add error style

* fix typo

* resolve comments

* fix g3 test
parent 2f4299ad
......@@ -26,6 +26,7 @@ import 'package:gen_defaults/chip_input_template.dart';
import 'package:gen_defaults/dialog_template.dart';
import 'package:gen_defaults/fab_template.dart';
import 'package:gen_defaults/icon_button_template.dart';
import 'package:gen_defaults/input_decorator_template.dart';
import 'package:gen_defaults/navigation_bar_template.dart';
import 'package:gen_defaults/navigation_rail_template.dart';
import 'package:gen_defaults/surface_tint.dart';
......@@ -111,6 +112,7 @@ Future<void> main(List<String> args) async {
DialogTemplate('Dialog', '$materialLib/dialog.dart', tokens).updateFile();
FABTemplate('FAB', '$materialLib/floating_action_button.dart', tokens).updateFile();
IconButtonTemplate('IconButton', '$materialLib/icon_button.dart', tokens).updateFile();
InputDecoratorTemplate('InputDecorator', '$materialLib/input_decorator.dart', tokens).updateFile();
NavigationBarTemplate('NavigationBar', '$materialLib/navigation_bar.dart', tokens).updateFile();
NavigationRailTemplate('NavigationRail', '$materialLib/navigation_rail.dart', tokens).updateFile();
SurfaceTintTemplate('SurfaceTint', '$materialLib/elevation_overlay.dart', tokens).updateFile();
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'template.dart';
class InputDecoratorTemplate extends TokenTemplate {
const InputDecoratorTemplate(super.blockName, super.fileName, super.tokens, {
super.colorSchemePrefix = '_colors.',
super.textThemePrefix = '_textTheme.'
});
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _${blockName}DefaultsM3 extends InputDecorationTheme {
_${blockName}DefaultsM3(this.context)
: super();
final BuildContext context;
late final ColorScheme _colors = Theme.of(context).colorScheme;
late final TextTheme _textTheme = Theme.of(context).textTheme;
@override
TextStyle? get hintStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: Theme.of(context).disabledColor);
}
return TextStyle(color: Theme.of(context).hintColor);
});
@override
Color? get fillColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return ${componentColor("md.comp.filled-text-field.disabled.container")};
}
return ${componentColor("md.comp.filled-text-field.container")};
});
@override
BorderSide? get activeIndicatorBorder => MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return ${border('md.comp.filled-text-field.error.hover.active-indicator')};
}
if (states.contains(MaterialState.focused)) {
return ${border('md.comp.filled-text-field.error.focus.active-indicator')};
}
return ${border('md.comp.filled-text-field.error.active-indicator')};
}
if (states.contains(MaterialState.hovered)) {
return ${border('md.comp.filled-text-field.hover.active-indicator')};
}
if (states.contains(MaterialState.focused)) {
return ${border('md.comp.filled-text-field.focus.active-indicator')};
}
if (states.contains(MaterialState.disabled)) {
return ${border('md.comp.filled-text-field.disabled.active-indicator')};
}
return ${border('md.comp.filled-text-field.active-indicator')};
});
@override
BorderSide? get outlineBorder => MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return ${border('md.comp.outlined-text-field.error.hover.outline')};
}
if (states.contains(MaterialState.focused)) {
return ${border('md.comp.outlined-text-field.error.focus.outline')};
}
return ${border('md.comp.outlined-text-field.error.outline')};
}
if (states.contains(MaterialState.hovered)) {
return ${border('md.comp.outlined-text-field.hover.outline')};
}
if (states.contains(MaterialState.focused)) {
return ${border('md.comp.outlined-text-field.focus.outline')};
}
if (states.contains(MaterialState.disabled)) {
return ${border('md.comp.outlined-text-field.disabled.outline')};
}
return ${border('md.comp.outlined-text-field.outline')};
});
@override
Color? get iconColor => ${componentColor("md.comp.filled-text-field.leading-icon")};
@override
Color? get prefixIconColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.filled-text-field.error.hover.leading-icon')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.filled-text-field.error.focus.leading-icon')};
}
return ${componentColor('md.comp.filled-text-field.error.leading-icon')};
}
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.filled-text-field.hover.leading-icon')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.filled-text-field.focus.leading-icon')};
}
if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.filled-text-field.disabled.leading-icon')};
}
return ${componentColor('md.comp.filled-text-field.leading-icon')};
});
@override
Color? get suffixIconColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.filled-text-field.error.hover.trailing-icon')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.filled-text-field.error.focus.trailing-icon')};
}
return ${componentColor('md.comp.filled-text-field.error.trailing-icon')};
}
if (states.contains(MaterialState.hovered)) {
return ${componentColor('md.comp.filled-text-field.hover.trailing-icon')};
}
if (states.contains(MaterialState.focused)) {
return ${componentColor('md.comp.filled-text-field.focus.trailing-icon')};
}
if (states.contains(MaterialState.disabled)) {
return ${componentColor('md.comp.filled-text-field.disabled.trailing-icon')};
}
return ${componentColor('md.comp.filled-text-field.trailing-icon')};
});
@override
TextStyle? get labelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= ${textStyle("md.comp.filled-text-field.label-text")} ?? const TextStyle();
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.hover.label-text')});
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.focus.label-text')});
}
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.label-text')});
}
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.hover.label-text')});
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.focus.label-text')});
}
if (states.contains(MaterialState.disabled)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.disabled.label-text')});
}
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.label-text')});
});
@override
TextStyle? get floatingLabelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= ${textStyle("md.comp.filled-text-field.label-text")} ?? const TextStyle();
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.hover.label-text')});
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.focus.label-text')});
}
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.label-text')});
}
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.hover.label-text')});
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.focus.label-text')});
}
if (states.contains(MaterialState.disabled)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.disabled.label-text')});
}
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.label-text')});
});
@override
TextStyle? get helperStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= ${textStyle("md.comp.filled-text-field.supporting-text")} ?? const TextStyle();
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.hover.supporting-text')});
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.focus.supporting-text')});
}
if (states.contains(MaterialState.disabled)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.disabled.supporting-text')});
}
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.supporting-text')});
});
@override
TextStyle? get errorStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= ${textStyle("md.comp.filled-text-field.supporting-text")} ?? const TextStyle();
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.hover.supporting-text')});
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.focus.supporting-text')});
}
return textStyle.copyWith(color:${componentColor('md.comp.filled-text-field.error.supporting-text')});
});
}
''';
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for Material Design 3 TextFields.
import 'package:flutter/material.dart';
void main() { runApp(const TextFieldExamplesApp()); }
class TextFieldExamplesApp extends StatelessWidget {
const TextFieldExamplesApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
home: Scaffold(
appBar: AppBar(title: const Text('TextField Examples')),
body: Column(
children: const <Widget>[
Spacer(),
FilledTextFieldExample(),
OutlinedTextFieldExample(),
Spacer(),
],
),
),
);
}
}
/// An example of the filled text field type.
///
/// A filled [TextField] with default settings matching the spec:
/// https://m3.material.io/components/text-fields/specs#6d654d1d-262e-4697-858c-9a75e8e7c81d
class FilledTextFieldExample extends StatelessWidget {
const FilledTextFieldExample({ super.key });
@override
Widget build(BuildContext context) {
return const TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
suffixIcon: Icon(Icons.clear),
labelText: 'Filled',
hintText: 'hint text',
helperText: 'supporting text',
filled: true,
)
);
}
}
/// An example of the outlined text field type.
///
/// A Outlined [TextField] with default settings matching the spec:
/// https://m3.material.io/components/text-fields/specs#68b00bd6-ab40-4b4f-93d9-ed1fbbc5d06e
class OutlinedTextFieldExample extends StatelessWidget {
const OutlinedTextFieldExample({ super.key });
@override
Widget build(BuildContext context) {
return const TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
suffixIcon: Icon(Icons.clear),
labelText: 'Outlined',
hintText: 'hint text',
helperText: 'supporting text',
border: OutlineInputBorder(),
),
);
}
}
......@@ -9,10 +9,13 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'constants.dart';
import 'input_border.dart';
import 'material.dart';
import 'material_state.dart';
import 'text_theme.dart';
import 'theme.dart';
import 'theme_data.dart';
......@@ -1944,14 +1947,15 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
}
}
Color _getActiveColor(ThemeData themeData) {
if (isFocused) {
return themeData.colorScheme.primary;
Color _getDefaultM2BorderColor(ThemeData themeData) {
if (!decoration.enabled && !isFocused) {
return ((decoration.filled ?? false) && !(decoration.border?.isOutline ?? false))
? Colors.transparent
: themeData.disabledColor;
}
if (decoration.errorText != null) {
return themeData.errorColor;
}
return themeData.hintColor;
}
Color _getDefaultBorderColor(ThemeData themeData) {
if (isFocused) {
return themeData.colorScheme.primary;
}
......@@ -1966,27 +1970,14 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
return enabledColor;
}
Color _getFillColor(ThemeData themeData) {
Color _getFillColor(ThemeData themeData, InputDecorationTheme defaults) {
if (decoration.filled != true) { // filled == null same as filled == false
return Colors.transparent;
}
if (decoration.fillColor != null) {
return MaterialStateProperty.resolveAs(decoration.fillColor!, materialState);
}
// dark theme: 10% white (enabled), 5% white (disabled)
// light theme: 4% black (enabled), 2% black (disabled)
const Color darkEnabled = Color(0x1AFFFFFF);
const Color darkDisabled = Color(0x0DFFFFFF);
const Color lightEnabled = Color(0x0A000000);
const Color lightDisabled = Color(0x05000000);
switch (themeData.brightness) {
case Brightness.dark:
return decoration.enabled ? darkEnabled : darkDisabled;
case Brightness.light:
return decoration.enabled ? lightEnabled : lightDisabled;
}
return MaterialStateProperty.resolveAs(defaults.fillColor!, materialState);
}
Color _getHoverColor(ThemeData themeData) {
......@@ -1996,35 +1987,19 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
return decoration.hoverColor ?? themeData.inputDecorationTheme.hoverColor ?? themeData.hoverColor;
}
Color _getIconColor(ThemeData themeData) {
Color resolveIconColor(Set<MaterialState> states) {
if (states.contains(MaterialState.disabled) && !states.contains(MaterialState.focused)) {
return themeData.disabledColor;
}
if (states.contains(MaterialState.focused)) {
return themeData.colorScheme.primary;
}
switch (themeData.brightness) {
case Brightness.dark:
return Colors.white70;
case Brightness.light:
return Colors.black45;
}
}
Color _getIconColor(ThemeData themeData, InputDecorationTheme defaults) {
return MaterialStateProperty.resolveAs(themeData.inputDecorationTheme.iconColor, materialState)
?? MaterialStateProperty.resolveWith(resolveIconColor).resolve(materialState);
?? MaterialStateProperty.resolveAs(defaults.iconColor!, materialState);
}
Color _getPrefixIconColor(ThemeData themeData) {
Color _getPrefixIconColor(ThemeData themeData, InputDecorationTheme defaults) {
return MaterialStateProperty.resolveAs(themeData.inputDecorationTheme.prefixIconColor, materialState)
?? _getIconColor(themeData);
?? MaterialStateProperty.resolveAs(defaults.prefixIconColor!, materialState);
}
Color _getSuffixIconColor(ThemeData themeData) {
Color _getSuffixIconColor(ThemeData themeData, InputDecorationTheme defaults) {
return MaterialStateProperty.resolveAs(themeData.inputDecorationTheme.suffixIconColor, materialState)
?? _getIconColor(themeData);
?? MaterialStateProperty.resolveAs(defaults.suffixIconColor!, materialState);
}
// True if the label will be shown and the hint will not.
......@@ -2042,10 +2017,8 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
// The base style for the inline label when they're displayed "inline",
// i.e. when they appear in place of the empty text field.
TextStyle _getInlineLabelStyle(ThemeData themeData) {
final TextStyle defaultStyle = TextStyle(
color: decoration.enabled ? themeData.hintColor : themeData.disabledColor,
);
TextStyle _getInlineLabelStyle(ThemeData themeData, InputDecorationTheme defaults) {
final TextStyle defaultStyle = MaterialStateProperty.resolveAs(defaults.labelStyle!, materialState);
final TextStyle? style = MaterialStateProperty.resolveAs(decoration.labelStyle, materialState)
?? MaterialStateProperty.resolveAs(themeData.inputDecorationTheme.labelStyle, materialState);
......@@ -2059,10 +2032,8 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
// The base style for the inline hint when they're displayed "inline",
// i.e. when they appear in place of the empty text field.
TextStyle _getInlineHintStyle(ThemeData themeData) {
final TextStyle defaultStyle = TextStyle(
color: decoration.enabled ? themeData.hintColor : themeData.disabledColor,
);
TextStyle _getInlineHintStyle(ThemeData themeData, InputDecorationTheme defaults) {
final TextStyle defaultStyle = MaterialStateProperty.resolveAs(defaults.hintStyle!, materialState);
final TextStyle? style = MaterialStateProperty.resolveAs(decoration.hintStyle, materialState)
?? MaterialStateProperty.resolveAs(themeData.inputDecorationTheme.hintStyle, materialState);
......@@ -2073,15 +2044,12 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
.merge(style);
}
TextStyle _getFloatingLabelStyle(ThemeData themeData) {
TextStyle getFallbackTextStyle() {
final Color color = decoration.errorText != null
? decoration.errorStyle?.color ?? themeData.errorColor
: _getActiveColor(themeData);
return TextStyle(color: decoration.enabled ? color : themeData.disabledColor)
.merge(decoration.floatingLabelStyle ?? decoration.labelStyle);
TextStyle _getFloatingLabelStyle(ThemeData themeData, InputDecorationTheme defaults) {
TextStyle defaultTextStyle = MaterialStateProperty.resolveAs(defaults.floatingLabelStyle!, materialState);
if (decoration.errorText != null && decoration.errorStyle?.color != null) {
defaultTextStyle = defaultTextStyle.copyWith(color: decoration.errorStyle?.color);
}
defaultTextStyle = defaultTextStyle.merge(decoration.floatingLabelStyle ?? decoration.labelStyle);
final TextStyle? style = MaterialStateProperty.resolveAs(decoration.floatingLabelStyle, materialState)
?? MaterialStateProperty.resolveAs(themeData.inputDecorationTheme.floatingLabelStyle, materialState);
......@@ -2089,18 +2057,18 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
return themeData.textTheme.subtitle1!
.merge(widget.baseStyle)
.copyWith(height: 1)
.merge(getFallbackTextStyle())
.merge(defaultTextStyle)
.merge(style);
}
TextStyle _getHelperStyle(ThemeData themeData) {
final Color color = decoration.enabled ? themeData.hintColor : Colors.transparent;
return themeData.textTheme.caption!.copyWith(color: color).merge(MaterialStateProperty.resolveAs(decoration.helperStyle, materialState));
TextStyle _getHelperStyle(ThemeData themeData, InputDecorationTheme defaults) {
return MaterialStateProperty.resolveAs(defaults.helperStyle!, materialState)
.merge(MaterialStateProperty.resolveAs(decoration.helperStyle, materialState));
}
TextStyle _getErrorStyle(ThemeData themeData) {
final Color color = decoration.enabled ? themeData.errorColor : Colors.transparent;
return themeData.textTheme.caption!.copyWith(color: color).merge(decoration.errorStyle);
TextStyle _getErrorStyle(ThemeData themeData, InputDecorationTheme defaults) {
return MaterialStateProperty.resolveAs(defaults.errorStyle!, materialState)
.merge(decoration.errorStyle);
}
Set<MaterialState> get materialState {
......@@ -2112,7 +2080,8 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
};
}
InputBorder _getDefaultBorder(ThemeData themeData) {
InputBorder _getDefaultBorder(ThemeData themeData, InputDecorationTheme defaults) {
final InputBorder border = MaterialStateProperty.resolveAs(decoration.border, materialState)
?? const UnderlineInputBorder();
......@@ -2124,34 +2093,39 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
return border;
}
final Color borderColor;
if (decoration.enabled || isFocused) {
borderColor = decoration.errorText == null
? _getDefaultBorderColor(themeData)
: themeData.errorColor;
} else {
borderColor = ((decoration.filled ?? false) && !(decoration.border?.isOutline ?? false))
? Colors.transparent
: themeData.disabledColor;
if (themeData.useMaterial3) {
if (decoration.filled!) {
return border.copyWith(
borderSide: MaterialStateProperty.resolveAs(defaults.activeIndicatorBorder, materialState),
);
} else {
return border.copyWith(
borderSide: MaterialStateProperty.resolveAs(defaults.outlineBorder, materialState),
);
}
}
final double borderWeight;
if (decoration.isCollapsed || decoration.border == InputBorder.none || !decoration.enabled) {
borderWeight = 0.0;
} else {
borderWeight = isFocused ? 2.0 : 1.0;
else{
return border.copyWith(
borderSide: BorderSide(
color: _getDefaultM2BorderColor(themeData),
width: (decoration.isCollapsed || decoration.border == InputBorder.none || !decoration.enabled)
? 0.0
: isFocused ? 2.0 : 1.0,
),
);
}
return border.copyWith(borderSide: BorderSide(color: borderColor, width: borderWeight));
}
@override
Widget build(BuildContext context) {
final ThemeData themeData = Theme.of(context);
final TextStyle labelStyle = _getInlineLabelStyle(themeData);
final InputDecorationTheme defaults =
Theme.of(context).useMaterial3 ? _InputDecoratorDefaultsM3(context) : _InputDecoratorDefaultsM2(context);
final TextStyle labelStyle = _getInlineLabelStyle(themeData, defaults);
final TextBaseline textBaseline = labelStyle.textBaseline!;
final TextStyle hintStyle = _getInlineHintStyle(themeData);
final TextStyle hintStyle = _getInlineHintStyle(themeData, defaults);
final String? hintText = decoration.hintText;
final Widget? hint = hintText == null ? null : AnimatedOpacity(
opacity: (isEmpty && !_hasInlineLabel) ? 1.0 : 0.0,
......@@ -2177,13 +2151,13 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
} else {
border = isError ? decoration.errorBorder : decoration.enabledBorder;
}
border ??= _getDefaultBorder(themeData);
border ??= _getDefaultBorder(themeData, defaults);
final Widget container = _BorderContainer(
border: border,
gap: _borderGap,
gapAnimation: _floatingLabelController.view,
fillColor: _getFillColor(themeData),
fillColor: _getFillColor(themeData, defaults),
hoverColor: _getHoverColor(themeData),
isHovering: isHovering,
);
......@@ -2198,7 +2172,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
duration:_kTransitionDuration,
curve: _kTransitionCurve,
style: widget._labelShouldWithdraw
? _getFloatingLabelStyle(themeData)
? _getFloatingLabelStyle(themeData, defaults)
: labelStyle,
child: decoration.label ?? Text(
decoration.labelText!,
......@@ -2234,7 +2208,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
padding: const EdgeInsetsDirectional.only(end: 16.0),
child: IconTheme.merge(
data: IconThemeData(
color: _getIconColor(themeData),
color: _getIconColor(themeData, defaults),
size: iconSize,
),
child: decoration.icon!,
......@@ -2254,7 +2228,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
),
child: IconTheme.merge(
data: IconThemeData(
color: _getPrefixIconColor(themeData),
color: _getPrefixIconColor(themeData, defaults),
size: iconSize,
),
child: decoration.prefixIcon!,
......@@ -2275,7 +2249,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
),
child: IconTheme.merge(
data: IconThemeData(
color: _getSuffixIconColor(themeData),
color: _getSuffixIconColor(themeData, defaults),
size: iconSize,
),
child: decoration.suffixIcon!,
......@@ -2286,10 +2260,10 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
final Widget helperError = _HelperError(
textAlign: textAlign,
helperText: decoration.helperText,
helperStyle: _getHelperStyle(themeData),
helperStyle: _getHelperStyle(themeData, defaults),
helperMaxLines: decoration.helperMaxLines,
errorText: decoration.errorText,
errorStyle: _getErrorStyle(themeData),
errorStyle: _getErrorStyle(themeData, defaults),
errorMaxLines: decoration.errorMaxLines,
);
......@@ -2302,7 +2276,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
liveRegion: isFocused,
child: Text(
decoration.counterText!,
style: _getHelperStyle(themeData).merge(MaterialStateProperty.resolveAs(decoration.counterStyle, materialState)),
style: _getHelperStyle(themeData, defaults).merge(MaterialStateProperty.resolveAs(decoration.counterStyle, materialState)),
overflow: TextOverflow.ellipsis,
semanticsLabel: decoration.semanticCounterText,
),
......@@ -2325,14 +2299,18 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
if (decoration.filled ?? false) {
contentPadding = decorationContentPadding ?? (decorationIsDense
? const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0)
: const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0));
: themeData.useMaterial3
? const EdgeInsets.fromLTRB(12.0, 12.75, 12.0, 12.75)
: const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0));
} else {
// Not left or right padding for underline borders that aren't filled
// is a small concession to backwards compatibility. This eliminates
// the most noticeable layout change introduced by #13734.
contentPadding = decorationContentPadding ?? (decorationIsDense
? const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0)
: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 12.0));
: themeData.useMaterial3
? const EdgeInsets.fromLTRB(0.0, 12.75, 0.0, 12.75)
: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 12.0));
}
} else {
floatingLabelHeight = 0.0;
......@@ -3752,6 +3730,8 @@ class InputDecorationTheme with Diagnosticable {
this.counterStyle,
this.filled = false,
this.fillColor,
this.activeIndicatorBorder,
this.outlineBorder,
this.focusColor,
this.hoverColor,
this.errorBorder,
......@@ -3936,6 +3916,12 @@ class InputDecorationTheme with Diagnosticable {
/// true and bordered per the [border].
final Color? fillColor;
/// The borderSide of the OutlineInputBorder with `color` and `weight`.
final BorderSide? outlineBorder;
/// The borderSide of the UnderlineInputBorder with `color` and `weight`.
final BorderSide? activeIndicatorBorder;
/// The color to blend with the decoration's [fillColor] with, if [filled] is
/// true and the container has the input focus.
///
......@@ -4155,6 +4141,8 @@ class InputDecorationTheme with Diagnosticable {
TextStyle? counterStyle,
bool? filled,
Color? fillColor,
BorderSide? activeIndicatorBorder,
BorderSide? outlineBorder,
Color? focusColor,
Color? hoverColor,
InputBorder? errorBorder,
......@@ -4187,6 +4175,8 @@ class InputDecorationTheme with Diagnosticable {
counterStyle: counterStyle ?? this.counterStyle,
filled: filled ?? this.filled,
fillColor: fillColor ?? this.fillColor,
activeIndicatorBorder: activeIndicatorBorder ?? this.activeIndicatorBorder,
outlineBorder: outlineBorder ?? this.outlineBorder,
focusColor: focusColor ?? this.focusColor,
hoverColor: hoverColor ?? this.hoverColor,
errorBorder: errorBorder ?? this.errorBorder,
......@@ -4223,6 +4213,8 @@ class InputDecorationTheme with Diagnosticable {
filled,
Object.hash(
fillColor,
activeIndicatorBorder,
outlineBorder,
focusColor,
hoverColor,
errorBorder,
......@@ -4265,6 +4257,8 @@ class InputDecorationTheme with Diagnosticable {
&& other.floatingLabelAlignment == floatingLabelAlignment
&& other.filled == filled
&& other.fillColor == fillColor
&& other.activeIndicatorBorder == activeIndicatorBorder
&& other.outlineBorder == outlineBorder
&& other.focusColor == focusColor
&& other.hoverColor == hoverColor
&& other.errorBorder == errorBorder
......@@ -4302,6 +4296,8 @@ class InputDecorationTheme with Diagnosticable {
properties.add(DiagnosticsProperty<TextStyle>('counterStyle', counterStyle, defaultValue: defaultTheme.counterStyle));
properties.add(DiagnosticsProperty<bool>('filled', filled, defaultValue: defaultTheme.filled));
properties.add(ColorProperty('fillColor', fillColor, defaultValue: defaultTheme.fillColor));
properties.add(DiagnosticsProperty<BorderSide>('activeIndicatorBorder', activeIndicatorBorder, defaultValue: defaultTheme.activeIndicatorBorder));
properties.add(DiagnosticsProperty<BorderSide>('outlineBorder', outlineBorder, defaultValue: defaultTheme.outlineBorder));
properties.add(ColorProperty('focusColor', focusColor, defaultValue: defaultTheme.focusColor));
properties.add(ColorProperty('hoverColor', hoverColor, defaultValue: defaultTheme.hoverColor));
properties.add(DiagnosticsProperty<InputBorder>('errorBorder', errorBorder, defaultValue: defaultTheme.errorBorder));
......@@ -4314,3 +4310,335 @@ class InputDecorationTheme with Diagnosticable {
properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: defaultTheme.constraints));
}
}
class _InputDecoratorDefaultsM2 extends InputDecorationTheme {
const _InputDecoratorDefaultsM2(this.context)
: super();
final BuildContext context;
@override
TextStyle? get hintStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: Theme.of(context).disabledColor);
}
return TextStyle(color: Theme.of(context).hintColor);
});
@override
TextStyle? get labelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: Theme.of(context).disabledColor);
}
return TextStyle(color: Theme.of(context).hintColor);
});
@override
TextStyle? get floatingLabelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: Theme.of(context).disabledColor);
}
if (states.contains(MaterialState.error)) {
return TextStyle(color: Theme.of(context).errorColor);
}
if (states.contains(MaterialState.focused)) {
return TextStyle(color: Theme.of(context).colorScheme.primary);
}
return TextStyle(color: Theme.of(context).hintColor);
});
@override
TextStyle? get helperStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final ThemeData themeData= Theme.of(context);
if (states.contains(MaterialState.disabled)) {
return themeData.textTheme.caption!.copyWith(color: Colors.transparent);
}
return themeData.textTheme.caption!.copyWith(color: themeData.hintColor);
});
@override
TextStyle? get errorStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final ThemeData themeData= Theme.of(context);
if (states.contains(MaterialState.disabled)) {
return themeData.textTheme.caption!.copyWith(color: Colors.transparent);
}
return themeData.textTheme.caption!.copyWith(color: themeData.errorColor);
});
@override
Color? get fillColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
// dark theme: 5% white
// light theme: 2% black
switch (Theme.of(context).brightness) {
case Brightness.dark:
return const Color(0x0DFFFFFF);
case Brightness.light:
return const Color(0x05000000) ;
}
}
// dark theme: 10% white
// light theme: 4% black
switch (Theme.of(context).brightness) {
case Brightness.dark: return const Color(0x1AFFFFFF);
case Brightness.light:return const Color(0x0A000000) ;
}
});
@override
Color? get iconColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled) && !states.contains(MaterialState.focused)) {
return Theme.of(context).disabledColor;
}
if (states.contains(MaterialState.focused)) {
return Theme.of(context).colorScheme.primary;
}
switch (Theme.of(context).brightness) {
case Brightness.dark:
return Colors.white70;
case Brightness.light:
return Colors.black45;
}
});
@override
Color? get prefixIconColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled) && !states.contains(MaterialState.focused)) {
return Theme.of(context).disabledColor;
}
if (states.contains(MaterialState.focused)) {
return Theme.of(context).colorScheme.primary;
}
switch (Theme.of(context).brightness) {
case Brightness.dark:
return Colors.white70;
case Brightness.light:
return Colors.black45;
}
});
@override
Color? get suffixIconColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled) && !states.contains(MaterialState.focused)) {
return Theme.of(context).disabledColor;
}
if (states.contains(MaterialState.focused)) {
return Theme.of(context).colorScheme.primary;
}
switch (Theme.of(context).brightness) {
case Brightness.dark:
return Colors.white70;
case Brightness.light:
return Colors.black45;
}
});
}
// BEGIN GENERATED TOKEN PROPERTIES - InputDecorator
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: v0_101
// Generated version v0_101
class _InputDecoratorDefaultsM3 extends InputDecorationTheme {
_InputDecoratorDefaultsM3(this.context)
: super();
final BuildContext context;
late final ColorScheme _colors = Theme.of(context).colorScheme;
late final TextTheme _textTheme = Theme.of(context).textTheme;
@override
TextStyle? get hintStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return TextStyle(color: Theme.of(context).disabledColor);
}
return TextStyle(color: Theme.of(context).hintColor);
});
@override
Color? get fillColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.disabled)) {
return _colors.onSurface.withOpacity(0.04);
}
return _colors.surfaceVariant;
});
@override
BorderSide? get activeIndicatorBorder => MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return BorderSide(color: _colors.onErrorContainer);
}
if (states.contains(MaterialState.focused)) {
return BorderSide(color: _colors.error);
}
return BorderSide(color: _colors.error);
}
if (states.contains(MaterialState.hovered)) {
return BorderSide(color: _colors.onSurface);
}
if (states.contains(MaterialState.focused)) {
return BorderSide(color: _colors.primary);
}
if (states.contains(MaterialState.disabled)) {
return BorderSide(color: _colors.onSurface.withOpacity(0.38));
}
return BorderSide(color: _colors.onSurfaceVariant);
});
@override
BorderSide? get outlineBorder => MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return BorderSide(color: _colors.onErrorContainer);
}
if (states.contains(MaterialState.focused)) {
return BorderSide(color: _colors.error);
}
return BorderSide(color: _colors.error);
}
if (states.contains(MaterialState.hovered)) {
return BorderSide(color: _colors.onSurface);
}
if (states.contains(MaterialState.focused)) {
return BorderSide(color: _colors.primary, width: 2.0);
}
if (states.contains(MaterialState.disabled)) {
return BorderSide(color: _colors.onSurface.withOpacity(0.12));
}
return BorderSide(color: _colors.outline);
});
@override
Color? get iconColor => _colors.onSurfaceVariant;
@override
Color? get prefixIconColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return _colors.onSurfaceVariant;
}
if (states.contains(MaterialState.focused)) {
return _colors.onSurfaceVariant;
}
return _colors.onSurfaceVariant;
}
if (states.contains(MaterialState.hovered)) {
return _colors.onSurfaceVariant;
}
if (states.contains(MaterialState.focused)) {
return _colors.onSurfaceVariant;
}
if (states.contains(MaterialState.disabled)) {
return _colors.onSurface.withOpacity(0.38);
}
return _colors.onSurfaceVariant;
});
@override
Color? get suffixIconColor => MaterialStateColor.resolveWith((Set<MaterialState> states) {
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return _colors.onErrorContainer;
}
if (states.contains(MaterialState.focused)) {
return _colors.error;
}
return _colors.error;
}
if (states.contains(MaterialState.hovered)) {
return _colors.onSurfaceVariant;
}
if (states.contains(MaterialState.focused)) {
return _colors.onSurfaceVariant;
}
if (states.contains(MaterialState.disabled)) {
return _colors.onSurface.withOpacity(0.38);
}
return _colors.onSurfaceVariant;
});
@override
TextStyle? get labelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= _textTheme.bodyLarge ?? const TextStyle();
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:_colors.onErrorContainer);
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:_colors.error);
}
return textStyle.copyWith(color:_colors.error);
}
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:_colors.onSurfaceVariant);
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:_colors.primary);
}
if (states.contains(MaterialState.disabled)) {
return textStyle.copyWith(color:_colors.onSurface.withOpacity(0.38));
}
return textStyle.copyWith(color:_colors.onSurfaceVariant);
});
@override
TextStyle? get floatingLabelStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= _textTheme.bodyLarge ?? const TextStyle();
if(states.contains(MaterialState.error)) {
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:_colors.onErrorContainer);
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:_colors.error);
}
return textStyle.copyWith(color:_colors.error);
}
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:_colors.onSurfaceVariant);
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:_colors.primary);
}
if (states.contains(MaterialState.disabled)) {
return textStyle.copyWith(color:_colors.onSurface.withOpacity(0.38));
}
return textStyle.copyWith(color:_colors.onSurfaceVariant);
});
@override
TextStyle? get helperStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= _textTheme.bodySmall ?? const TextStyle();
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:_colors.onSurfaceVariant);
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:_colors.onSurfaceVariant);
}
if (states.contains(MaterialState.disabled)) {
return textStyle.copyWith(color:_colors.onSurface.withOpacity(0.38));
}
return textStyle.copyWith(color:_colors.onSurfaceVariant);
});
@override
TextStyle? get errorStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
final TextStyle textStyle= _textTheme.bodySmall ?? const TextStyle();
if (states.contains(MaterialState.hovered)) {
return textStyle.copyWith(color:_colors.error);
}
if (states.contains(MaterialState.focused)) {
return textStyle.copyWith(color:_colors.error);
}
return textStyle.copyWith(color:_colors.error);
});
}
// END GENERATED TOKEN PROPERTIES - InputDecorator
......@@ -1183,6 +1183,7 @@ class ThemeData with Diagnosticable {
/// * FAB: [FloatingActionButton]
/// * Extended FAB: [FloatingActionButton.extended]
/// * Cards: [Card]
/// * TextFields: [TextField] together with its [InputDecoration]
/// * Chips:
/// - [ActionChip] (used for Assist and Suggestion chips),
/// - [FilterChip], [ChoiceChip] (used for single selection filter chips),
......
......@@ -24,6 +24,7 @@ Widget buildInputDecorator({
bool isEmpty = false,
bool isFocused = false,
bool isHovering = false,
bool useMaterial3 = false,
TextStyle? baseStyle,
TextAlignVertical? textAlignVertical,
VisualDensity? visualDensity,
......@@ -40,6 +41,7 @@ Widget buildInputDecorator({
data: (theme ?? Theme.of(context)).copyWith(
inputDecorationTheme: inputDecorationTheme,
visualDensity: visualDensity,
useMaterial3: useMaterial3,
),
child: Align(
alignment: Alignment.topLeft,
......@@ -145,10 +147,12 @@ double getOpacity(WidgetTester tester, String textValue) {
}
void main() {
for(final bool useMaterial3 in <bool>[true, false]){
testWidgets('InputDecorator input/label text layout', (WidgetTester tester) async {
// The label appears above the input text
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -166,16 +170,17 @@ void main() {
// 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
// The label appears within the input when there is no text content
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -185,11 +190,12 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
// The label appears above the input text when there is no content and floatingLabelBehavior is always
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -200,11 +206,12 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
// The label appears within the input text when there is content and floatingLabelBehavior is never
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
decoration: const InputDecoration(
labelText: 'label',
......@@ -214,7 +221,7 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
// Overall height for this InputDecorator is 56dps:
// 12 - top padding
......@@ -223,12 +230,13 @@ void main() {
// 16 - input text (ahem font size 16dps)
// 12 - bottom padding
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
// isFocused: true increases the border's weight from 1.0 to 2.0
// but does not change the overall height.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
isFocused: true,
decoration: const InputDecoration(
......@@ -238,16 +246,17 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
// isEmpty: true causes the label to be aligned with the input text
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
......@@ -267,16 +276,17 @@ void main() {
}
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
// isFocused: true causes the label to move back up above the input text.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
decoration: const InputDecoration(
......@@ -296,10 +306,10 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
......@@ -307,6 +317,7 @@ void main() {
// The widget's size and layout is the same as for enabled: true.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
......@@ -316,16 +327,17 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(getBorderWeight(tester), 0.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getBorderWeight(tester), useMaterial3 ? 1.0 : 0.0);
// enabled: false produces a transparent border if filled: true.
// The widget's size and layout is the same as for enabled: true.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
......@@ -336,16 +348,18 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(getBorderColor(tester), Colors.transparent);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
final ThemeData theme = ThemeData.from(colorScheme: const ColorScheme.light());
expect(getBorderColor(tester), useMaterial3 ? theme.colorScheme.onSurface.withOpacity(0.38) : Colors.transparent);
// alignLabelWithHint: true positions the label at the text baseline,
// aligned with the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
......@@ -356,8 +370,10 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('label')).dy, tester.getTopLeft(find.text('hint')).dy);
expect(tester.getBottomLeft(find.text('label')).dy, tester.getBottomLeft(find.text('hint')).dy);
if(!useMaterial3) {
expect(tester.getTopLeft(find.text('label')).dy, tester.getTopLeft(find.text('hint')).dy);
expect(tester.getBottomLeft(find.text('label')).dy, tester.getBottomLeft(find.text('hint')).dy);
}
});
testWidgets('InputDecorator input/label widget layout', (WidgetTester tester) async {
......@@ -366,6 +382,7 @@ void main() {
// The label appears above the input text.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -394,16 +411,17 @@ void main() {
// 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, 12.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 12.75 :12.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, useMaterial3 ? 23.25 :24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
// The label appears within the input when there is no text content.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -424,12 +442,13 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.byKey(key)).dy, 20.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 21.0 :20.0);
// The label appears above the input text when there is no content and the
// floatingLabelBehavior is set to always.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -451,12 +470,13 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.byKey(key)).dy, 12.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 12.75 :12.0);
// The label appears within the input text when there is content and
// the floatingLabelBehavior is set to never.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
decoration: const InputDecoration(
label: Text.rich(
......@@ -477,7 +497,7 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.byKey(key)).dy, 20.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 21 :20.0);
// Overall height for this InputDecorator is 56dps:
// 12 - top padding
......@@ -486,12 +506,13 @@ void main() {
// 16 - input text (ahem font size 16dps)
// 12 - bottom padding
expect(tester.getTopLeft(find.byKey(key)).dy, 20.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 21 :20.0);
// isFocused: true increases the border's weight from 1.0 to 2.0
// but does not change the overall height.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
isFocused: true,
decoration: const InputDecoration(
......@@ -512,16 +533,17 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, 12.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 12.75 :12.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, useMaterial3 ? 23.25 :24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
// isEmpty: true causes the label to be aligned with the input text.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
label: Text.rich(
......@@ -551,16 +573,17 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, 20.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, 36.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 :28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 :44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 21 :20.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, useMaterial3 ? 35 :36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
// isFocused: true causes the label to move back up above the input text.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
decoration: const InputDecoration(
......@@ -593,10 +616,10 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, 12.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 :28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 :44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 12.75 :12.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, useMaterial3 ? 23.25 :24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
......@@ -604,6 +627,7 @@ void main() {
// The widget's size and layout is the same as for enabled: true.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
label: Text.rich(
......@@ -624,16 +648,17 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, 20.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, 36.0);
expect(getBorderWeight(tester), 0.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 :28.0);
expect(tester.getBottomLeft(find.text('text')).dy,useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 21 :20.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, useMaterial3 ? 35 :36.0);
expect(getBorderWeight(tester),useMaterial3 ? 1.0 : 0.0);
// enabled: false produces a transparent border if filled: true.
// The widget's size and layout is the same as for enabled: true.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
label: Text.rich(
......@@ -655,16 +680,18 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, 20.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, 36.0);
expect(getBorderColor(tester), Colors.transparent);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25: 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25: 44.0);
expect(tester.getTopLeft(find.byKey(key)).dy, useMaterial3 ? 21: 20.0);
expect(tester.getBottomLeft(find.byKey(key)).dy, useMaterial3 ? 35: 36.0);
final ThemeData theme = ThemeData.from(colorScheme: const ColorScheme.light());
expect(getBorderColor(tester), useMaterial3 ? theme.colorScheme.onSurface.withOpacity(0.38) : Colors.transparent);
// alignLabelWithHint: true positions the label at the text baseline,
// aligned with the hint.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
label: Text.rich(
......@@ -686,8 +713,11 @@ void main() {
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.byKey(key)).dy, tester.getTopLeft(find.text('hint')).dy);
expect(tester.getBottomLeft(find.byKey(key)).dy, tester.getBottomLeft(find.text('hint')).dy);
if(!useMaterial3) {
expect(tester.getTopLeft(find.byKey(key)).dy, tester.getTopLeft(find.text('hint')).dy);
expect(tester.getBottomLeft(find.byKey(key)).dy, tester.getBottomLeft(find.text('hint')).dy);
}
});
group('alignLabelWithHint', () {
......@@ -909,6 +939,7 @@ void main() {
// The hint aligns with the input text
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -932,6 +963,7 @@ void main() {
// Label is visible, hint is not (opacity 0.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -959,10 +991,10 @@ void main() {
// The label is not floating so it's vertically centered.
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
......@@ -970,6 +1002,7 @@ void main() {
// Label moves upwards, hint is visible (opacity 1.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
decoration: const InputDecoration(
......@@ -992,18 +1025,19 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, 28.0);
expect(tester.getBottomLeft(find.text('hint')).dy, 44.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 :28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 :44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, useMaterial3 ? 27.25 :28.0);
expect(tester.getBottomLeft(find.text('hint')).dy, useMaterial3 ? 43.25 :44.0);
expect(getOpacity(tester, 'hint'), 1.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: true,
decoration: const InputDecoration(
labelText: 'label',
......@@ -1025,12 +1059,12 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, 28.0);
expect(tester.getBottomLeft(find.text('hint')).dy, 44.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 :28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 :44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, useMaterial3 ? 27.25 :28.0);
expect(tester.getBottomLeft(find.text('hint')).dy, useMaterial3 ? 43.25 :44.0);
expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
......@@ -1040,6 +1074,7 @@ void main() {
// Label is visible, hint is not (opacity 0.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1066,18 +1101,19 @@ void main() {
// 16 - bottom padding (empty input text still appears here)
// The label is not floating so it's vertically centered.
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getTopLeft(find.text('text')).dy, 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, 40.0);
expect(tester.getTopLeft(find.text('label')).dy, 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, 32.0);
expect(tester.getSize(find.byType(InputDecorator)), Size(800.0, useMaterial3 ? 46.5 :48.0));
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 22.5 : 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 38.5 : 40.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 16.25 : 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 30.25 : 32.0);
expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderBottom(tester), 48.0);
expect(getBorderBottom(tester), useMaterial3 ? 46.5 : 48.0);
expect(getBorderWeight(tester), 1.0);
// Label is visible, hint is not (opacity 0.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
decoration: const InputDecoration(
......@@ -1088,13 +1124,13 @@ void main() {
),
);
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getTopLeft(find.text('text')).dy, 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, 40.0);
expect(tester.getSize(find.byType(InputDecorator)), Size(800.0, useMaterial3 ? 46.5 : 48.0));
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 22.5 : 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 38.5 : 40.0);
expect(tester.getTopLeft(find.text('label')).dy, 8.0);
expect(tester.getBottomLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 18.5 : 20.0);
expect(getOpacity(tester, 'hint'), 1.0);
expect(getBorderBottom(tester), 48.0);
expect(getBorderBottom(tester), useMaterial3 ? 46.5 : 48.0);
expect(getBorderWeight(tester), 2.0);
});
......@@ -1102,6 +1138,7 @@ void main() {
// Label is visible, hint is not (opacity 0.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1115,6 +1152,7 @@ void main() {
testWidgets('InputDecorator error/helper/counter layout', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1148,10 +1186,10 @@ void main() {
// isEmpty: true, the label is not floating
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 76.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 :44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
expect(tester.getTopLeft(find.text('helper')), const Offset(12.0, 64.0));
......@@ -1160,6 +1198,7 @@ void main() {
// If errorText is specified then the helperText isn't shown
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1175,10 +1214,10 @@ void main() {
// isEmpty: false, the label _is_ floating
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 76.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
expect(tester.getTopLeft(find.text('error')), const Offset(12.0, 64.0));
......@@ -1207,6 +1246,7 @@ void main() {
// The layout of the error/helper/counter subtext doesn't change for dense layout.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1222,18 +1262,19 @@ void main() {
await tester.pumpAndSettle();
// isEmpty: false, the label _is_ floating
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 68.0));
expect(tester.getTopLeft(find.text('text')).dy, 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, 40.0);
expect(tester.getSize(find.byType(InputDecorator)), Size(800.0, useMaterial3 ? 66.5 : 68.0));
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 22.5 : 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 38.5 : 40.0);
expect(tester.getTopLeft(find.text('label')).dy, 8.0);
expect(tester.getBottomLeft(find.text('label')).dy, 20.0);
expect(getBorderBottom(tester), 48.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 18.5 : 20.0);
expect(getBorderBottom(tester), useMaterial3 ? 46.5 : 48.0);
expect(getBorderWeight(tester), 1.0);
expect(tester.getTopLeft(find.text('error')), const Offset(12.0, 56.0));
expect(tester.getTopRight(find.text('counter')), const Offset(788.0, 56.0));
expect(tester.getTopLeft(find.text('error')), Offset(12.0, useMaterial3 ? 54.5 : 56.0));
expect(tester.getTopRight(find.text('counter')), Offset(788.0, useMaterial3 ? 54.5 : 56.0));
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1249,15 +1290,15 @@ void main() {
await tester.pumpAndSettle();
// isEmpty: false, the label is not floating
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 68.0));
expect(tester.getTopLeft(find.text('text')).dy, 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, 40.0);
expect(tester.getTopLeft(find.text('label')).dy, 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, 32.0);
expect(getBorderBottom(tester), 48.0);
expect(tester.getSize(find.byType(InputDecorator)), Size(800.0, useMaterial3 ? 66.5 : 68.0));
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 22.5 : 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 38.5 : 40.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 16.25 : 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 30.25 : 32.0);
expect(getBorderBottom(tester), useMaterial3 ? 46.5 : 48.0);
expect(getBorderWeight(tester), 1.0);
expect(tester.getTopLeft(find.text('error')), const Offset(12.0, 56.0));
expect(tester.getTopRight(find.text('counter')), const Offset(788.0, 56.0));
expect(tester.getTopLeft(find.text('error')), Offset(12.0, useMaterial3 ? 54.5 : 56.0));
expect(tester.getTopRight(find.text('counter')), Offset(788.0, useMaterial3 ? 54.5 : 56.0));
});
testWidgets('InputDecorator counter text, widget, and null', (WidgetTester tester) async {
......@@ -1369,6 +1410,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1400,6 +1442,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1421,6 +1464,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1445,6 +1489,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1475,6 +1520,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1495,6 +1541,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1515,6 +1562,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1534,6 +1582,7 @@ void main() {
testWidgets('InputDecorator prefix/suffix texts', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1571,6 +1620,7 @@ void main() {
testWidgets('InputDecorator icon/prefix/suffix', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1612,6 +1662,7 @@ void main() {
const Key sKey = Key('s');
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1638,17 +1689,17 @@ void main() {
// 4 - bottom prefix/suffix padding
// 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getSize(find.byType(InputDecorator)), Size(800.0, useMaterial3 ? 49.5 : 48.0));
expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getSize(find.byKey(pKey)).height, 24.0);
expect(tester.getSize(find.text('p')).height, 16.0);
expect(tester.getSize(find.byKey(sKey)).height, 24.0);
expect(tester.getSize(find.text('s')).height, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, 16.0);
expect(tester.getTopLeft(find.byKey(pKey)).dy, 12.0);
expect(tester.getTopLeft(find.text('p')).dy, 16.0);
expect(tester.getTopLeft(find.byKey(sKey)).dy, 12.0);
expect(tester.getTopLeft(find.text('s')).dy, 16.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 16.75 : 16.0);
expect(tester.getTopLeft(find.byKey(pKey)).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getTopLeft(find.text('p')).dy, useMaterial3 ? 16.75 : 16.0);
expect(tester.getTopLeft(find.byKey(sKey)).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getTopLeft(find.text('s')).dy, useMaterial3 ? 16.75 : 16.0);
expect(tester.getTopRight(find.byKey(sKey)).dx, 788.0);
expect(tester.getTopRight(find.text('s')).dx, 784.0);
......@@ -1662,6 +1713,7 @@ void main() {
const Key pKey = Key('p');
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1691,11 +1743,11 @@ void main() {
// 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)).width, 800.0);
expect(tester.getSize(find.byType(InputDecorator)).height, moreOrLessEquals(128.0, epsilon: .0001));
expect(tester.getSize(find.byType(InputDecorator)).height, moreOrLessEquals(useMaterial3 ? 129.5 : 128.0, epsilon: .0001));
expect(tester.getSize(find.text('text')).height, 20.0);
expect(tester.getSize(find.byKey(pKey)).height, 100.0);
expect(tester.getTopLeft(find.text('text')).dy, moreOrLessEquals(96, epsilon: .0001)); // 12 + 100 - 16
expect(tester.getTopLeft(find.byKey(pKey)).dy, 12.0);
expect(tester.getTopLeft(find.text('text')).dy, moreOrLessEquals(useMaterial3 ? 96.75 : 96, epsilon: .0001)); // 12 + 100 - 16
expect(tester.getTopLeft(find.byKey(pKey)).dy, useMaterial3 ? 12.75 : 12.0);
// layout is a row: [prefix text suffix]
expect(tester.getTopLeft(find.byKey(pKey)).dx, 12.0);
......@@ -1706,6 +1758,7 @@ void main() {
const Key pKey = Key('p');
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1755,6 +1808,7 @@ void main() {
testWidgets('InputDecorator prefixIcon/suffixIcon', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1775,7 +1829,7 @@ void main() {
expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getSize(find.byIcon(Icons.pages)).height, 48.0);
expect(tester.getSize(find.byIcon(Icons.satellite)).height, 48.0);
expect(tester.getTopLeft(find.text('text')).dy, 12.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getTopLeft(find.byIcon(Icons.pages)).dy, 0.0);
expect(tester.getTopLeft(find.byIcon(Icons.satellite)).dy, 0.0);
expect(tester.getTopRight(find.byIcon(Icons.satellite)).dx, 800.0);
......@@ -1790,6 +1844,7 @@ void main() {
testWidgets('InputDecorator prefixIconConstraints/suffixIconConstraints', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -1828,6 +1883,7 @@ void main() {
const Key prefixKey = Key('prefix');
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
prefixIcon: Padding(
padding: EdgeInsets.all(16.0),
......@@ -1853,6 +1909,7 @@ void main() {
// Label is visible, hint is not (opacity 0.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
visualDensity: VisualDensity.compact,
decoration: const InputDecoration(
......@@ -1864,10 +1921,10 @@ void main() {
// The label is not floating so it's vertically centered.
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getTopLeft(find.text('text')).dy, 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, 40.0);
expect(tester.getTopLeft(find.text('label')).dy, 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, 32.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 39.25 : 40.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 17 : 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 31.0 : 32.0);
expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderBottom(tester), 48.0);
expect(getBorderWeight(tester), 1.0);
......@@ -1875,6 +1932,7 @@ void main() {
// Label moves upwards, hint is visible (opacity 1.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
visualDensity: VisualDensity.compact,
......@@ -1898,18 +1956,19 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getTopLeft(find.text('text')).dy, 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, 40.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, 24.0);
expect(tester.getBottomLeft(find.text('hint')).dy, 40.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 39.25 : 40.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getBottomLeft(find.text('hint')).dy, useMaterial3 ? 39.25 : 40.0);
expect(getOpacity(tester, 'hint'), 1.0);
expect(getBorderBottom(tester), 48.0);
expect(getBorderWeight(tester), 2.0);
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: true,
visualDensity: VisualDensity.compact,
decoration: const InputDecoration(
......@@ -1932,12 +1991,12 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getTopLeft(find.text('text')).dy, 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, 40.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, 24.0);
expect(tester.getBottomLeft(find.text('hint')).dy, 40.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 39.25 : 40.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getBottomLeft(find.text('hint')).dy, useMaterial3 ? 39.25 : 40.0);
expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderBottom(tester), 48.0);
expect(getBorderWeight(tester), 2.0);
......@@ -1947,6 +2006,7 @@ void main() {
// Label is visible, hint is not (opacity 0.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
visualDensity: const VisualDensity(horizontal: 2.0, vertical: 2.0),
decoration: const InputDecoration(
......@@ -1958,10 +2018,10 @@ void main() {
// The label is not floating so it's vertically centered.
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 64.0));
expect(tester.getTopLeft(find.text('text')).dy, 32.0);
expect(tester.getBottomLeft(find.text('text')).dy, 48.0);
expect(tester.getTopLeft(find.text('label')).dy, 24.0);
expect(tester.getBottomLeft(find.text('label')).dy, 40.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 31.25 : 32.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 47.25 : 48.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 25.0 : 24.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 39.0 : 40.0);
expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderBottom(tester), 64.0);
expect(getBorderWeight(tester), 1.0);
......@@ -1969,6 +2029,7 @@ void main() {
// Label moves upwards, hint is visible (opacity 1.0).
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
visualDensity: const VisualDensity(horizontal: 2.0, vertical: 2.0),
......@@ -1992,18 +2053,19 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 64.0));
expect(tester.getTopLeft(find.text('text')).dy, 32.0);
expect(tester.getBottomLeft(find.text('text')).dy, 48.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, 32.0);
expect(tester.getBottomLeft(find.text('hint')).dy, 48.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 31.25 : 32.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 47.25 : 48.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, useMaterial3 ? 31.25 : 32.0);
expect(tester.getBottomLeft(find.text('hint')).dy, useMaterial3 ? 47.25 : 48.0);
expect(getOpacity(tester, 'hint'), 1.0);
expect(getBorderBottom(tester), 64.0);
expect(getBorderWeight(tester), 2.0);
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: true,
visualDensity: const VisualDensity(horizontal: 2.0, vertical: 2.0),
decoration: const InputDecoration(
......@@ -2026,12 +2088,12 @@ void main() {
await tester.pumpAndSettle();
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 64.0));
expect(tester.getTopLeft(find.text('text')).dy, 32.0);
expect(tester.getBottomLeft(find.text('text')).dy, 48.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, 32.0);
expect(tester.getBottomLeft(find.text('hint')).dy, 48.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 31.25 : 32.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 47.25 : 48.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(tester.getTopLeft(find.text('hint')).dy, useMaterial3 ? 31.25 : 32.0);
expect(tester.getBottomLeft(find.text('hint')).dy, useMaterial3 ? 47.25 : 48.0);
expect(getOpacity(tester, 'hint'), 0.0);
expect(getBorderBottom(tester), 64.0);
expect(getBorderWeight(tester), 2.0);
......@@ -2041,6 +2103,7 @@ void main() {
const Key prefixKey = Key('prefix');
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
prefixIcon: SizedBox(width: 100.0, height: 100.0, key: prefixKey),
filled: true,
......@@ -2061,7 +2124,9 @@ void main() {
group('constraints', () {
testWidgets('No InputDecorator constraints', (WidgetTester tester) async {
await tester.pumpWidget(buildInputDecorator());
await tester.pumpWidget(buildInputDecorator(
useMaterial3: useMaterial3,
));
// Should fill the screen width and be default height
expect(tester.getSize(find.byType(InputDecorator)), const Size(800, 48));
......@@ -2070,6 +2135,7 @@ void main() {
testWidgets('InputDecoratorThemeData constraints', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: ThemeData(
inputDecorationTheme: const InputDecorationTheme(
constraints: BoxConstraints(maxWidth: 300, maxHeight: 40),
......@@ -2085,6 +2151,7 @@ void main() {
testWidgets('InputDecorator constraints', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: ThemeData(
inputDecorationTheme: const InputDecorationTheme(
constraints: BoxConstraints(maxWidth: 300, maxHeight: 40),
......@@ -2108,6 +2175,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true, // so we have a tall input where align can vary
......@@ -2124,13 +2192,14 @@ void main() {
);
// Same as the default case above.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(12.0, epsilon: .0001));
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 12.75 : 12.0, epsilon: .0001));
});
testWidgets('align center', (WidgetTester tester) async {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2154,6 +2223,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2170,13 +2240,14 @@ void main() {
);
// Below the center aligned case.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(568.0, epsilon: .0001));
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 567.25 : 568.0, epsilon: .0001));
});
testWidgets('align as a double', (WidgetTester tester) async {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2193,7 +2264,7 @@ void main() {
);
// In between the center and bottom aligned cases.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(498.5, epsilon: .0001));
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 497.9375 : 498.5, epsilon: .0001));
});
});
......@@ -2202,6 +2273,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true, // so we have a tall input where align can vary
......@@ -2227,6 +2299,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2251,6 +2324,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2278,6 +2352,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -2298,8 +2373,8 @@ void main() {
);
// Same as the default case above.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(96, epsilon: .0001));
expect(tester.getTopLeft(find.byKey(pKey)).dy, 12.0);
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 96.75 : 96, epsilon: .0001));
expect(tester.getTopLeft(find.byKey(pKey)).dy, useMaterial3 ? 12.75 : 12.0);
});
testWidgets('InputDecorator tall prefix align center', (WidgetTester tester) async {
......@@ -2307,6 +2382,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -2327,8 +2403,8 @@ void main() {
);
// Same as the default case above.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(96.0, epsilon: .0001));
expect(tester.getTopLeft(find.byKey(pKey)).dy, 12.0);
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 96.75 : 96.0, epsilon: .0001));
expect(tester.getTopLeft(find.byKey(pKey)).dy, useMaterial3 ? 12.75 : 12.0);
});
testWidgets('InputDecorator tall prefix align bottom', (WidgetTester tester) async {
......@@ -2336,6 +2412,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -2356,8 +2433,8 @@ void main() {
);
// Top of the input + 100 prefix height - overlap
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(96.0, epsilon: .0001));
expect(tester.getTopLeft(find.byKey(pKey)).dy, 12.0);
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 96.75 : 96.0, epsilon: .0001));
expect(tester.getTopLeft(find.byKey(pKey)).dy, useMaterial3 ? 12.75 : 12.0);
});
});
......@@ -2367,6 +2444,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2398,6 +2476,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2431,6 +2510,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2462,6 +2542,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true,
......@@ -2494,6 +2575,7 @@ void main() {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true, // so we have a tall input where align can vary
......@@ -2512,13 +2594,14 @@ void main() {
// The label causes the text to start slightly lower than it would
// otherwise.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(28.0, epsilon: .0001));
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 27.25 : 28.0, epsilon: .0001));
});
testWidgets('align center', (WidgetTester tester) async {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true, // so we have a tall input where align can vary
......@@ -2537,13 +2620,14 @@ void main() {
// The label reduces the amount of space available for text, so the
// center is slightly lower.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(298.0, epsilon: .0001));
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 297.25 : 298.0, epsilon: .0001));
});
testWidgets('align bottom', (WidgetTester tester) async {
const String text = 'text';
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
expands: true, // so we have a tall input where align can vary
......@@ -2562,7 +2646,7 @@ void main() {
// The label reduces the amount of space available for text, but the
// bottom line is still in the same place.
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(568.0, epsilon: .0001));
expect(tester.getTopLeft(find.text(text)).dy, moreOrLessEquals(useMaterial3 ? 567.25 : 568.0, epsilon: .0001));
});
});
});
......@@ -2572,6 +2656,7 @@ void main() {
testWidgets('Centers when border', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
border: OutlineInputBorder(),
),
......@@ -2588,6 +2673,7 @@ void main() {
testWidgets('Centers when border and label', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
labelText: 'label',
border: OutlineInputBorder(),
......@@ -2605,6 +2691,7 @@ void main() {
testWidgets('Centers when border and contentPadding', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
border: OutlineInputBorder(),
contentPadding: EdgeInsets.fromLTRB(
......@@ -2625,6 +2712,7 @@ void main() {
testWidgets('Centers when border and contentPadding and label', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
labelText: 'label',
border: OutlineInputBorder(),
......@@ -2645,6 +2733,7 @@ void main() {
testWidgets('Centers when border and lopsided contentPadding and label', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
labelText: 'label',
border: OutlineInputBorder(),
......@@ -2668,6 +2757,7 @@ void main() {
testWidgets('top align includes padding', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
expands: true,
textAlignVertical: TextAlignVertical.top,
decoration: const InputDecoration(
......@@ -2691,6 +2781,7 @@ void main() {
testWidgets('center align ignores padding', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
expands: true,
textAlignVertical: TextAlignVertical.center,
decoration: const InputDecoration(
......@@ -2714,6 +2805,7 @@ void main() {
testWidgets('bottom align includes padding', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
expands: true,
textAlignVertical: TextAlignVertical.bottom,
decoration: const InputDecoration(
......@@ -2737,6 +2829,7 @@ void main() {
testWidgets('padding exceeds middle keeps top at middle', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
expands: true,
textAlignVertical: TextAlignVertical.top,
decoration: const InputDecoration(
......@@ -2762,6 +2855,7 @@ void main() {
testWidgets('counter text has correct right margin - LTR, not dense', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -2781,6 +2875,7 @@ void main() {
testWidgets('counter text has correct right margin - RTL, not dense', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
textDirection: TextDirection.rtl,
// isEmpty: false (default)
// isFocused: false (default)
......@@ -2800,6 +2895,7 @@ void main() {
testWidgets('counter text has correct right margin - LTR, dense', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -2820,6 +2916,7 @@ void main() {
testWidgets('counter text has correct right margin - RTL, dense', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
textDirection: TextDirection.rtl,
// isEmpty: false (default)
// isFocused: false (default)
......@@ -2840,6 +2937,7 @@ void main() {
testWidgets('InputDecorator error/helper/counter RTL layout', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
textDirection: TextDirection.rtl,
......@@ -2862,10 +2960,10 @@ void main() {
// 12 - [counter helper/error] (ahem font size 12dps)
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 76.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
expect(tester.getTopLeft(find.text('counter')), const Offset(12.0, 64.0));
......@@ -2874,6 +2972,7 @@ void main() {
// If both error and helper are specified, show the error
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
textDirection: TextDirection.rtl,
......@@ -2895,6 +2994,7 @@ void main() {
testWidgets('InputDecorator prefix/suffix RTL', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
textDirection: TextDirection.rtl,
......@@ -2929,10 +3029,11 @@ void main() {
// LTR: content left edge is contentPadding.start: 40.0
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
contentPadding: EdgeInsetsDirectional.only(start: 40.0, top: 12.0, bottom: 12.0),
decoration: InputDecoration(
contentPadding: EdgeInsetsDirectional.only(start: 40.0, top: useMaterial3 ? 12.75 : 12.0, bottom: useMaterial3 ? 12.75 : 12.0),
labelText: 'label',
hintText: 'hint',
filled: true,
......@@ -2947,11 +3048,12 @@ void main() {
// RTL: content right edge is 800 - contentPadding.start: 760.0.
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
isFocused: true, // label is floating, still adjusted for contentPadding
textDirection: TextDirection.rtl,
decoration: const InputDecoration(
contentPadding: EdgeInsetsDirectional.only(start: 40.0, top: 12.0, bottom: 12.0),
decoration: InputDecoration(
contentPadding: EdgeInsetsDirectional.only(start: 40.0, top: useMaterial3 ? 12.75 : 12.0, bottom: useMaterial3 ? 12.75 : 12.0),
labelText: 'label',
hintText: 'hint',
filled: true,
......@@ -2975,6 +3077,7 @@ void main() {
required FloatingLabelAlignment alignment,
bool borderIsOutline = false,
}) => buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
textDirection: textDirection,
......@@ -3193,6 +3296,7 @@ void main() {
testWidgets('InputDecorator prefix/suffix dense layout', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
isFocused: true,
decoration: const InputDecoration(
......@@ -3228,11 +3332,13 @@ void main() {
expect(tester.getTopRight(find.text('text')).dx, lessThanOrEqualTo(tester.getTopLeft(find.text('s')).dx));
expect(getBorderBottom(tester), 32.0);
expect(getBorderWeight(tester), 2.0);
expect(getBorderWeight(tester), useMaterial3 ? 1.0 : 2.0);
});
testWidgets('InputDecorator with empty InputDecoration', (WidgetTester tester) async {
await tester.pumpWidget(buildInputDecorator());
await tester.pumpWidget(buildInputDecorator(
useMaterial3: useMaterial3,
));
// Overall height for this InputDecorator is 40dps:
// 12 - top padding
......@@ -3251,6 +3357,7 @@ void main() {
const double verticalPadding = 1.0;
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default),
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -3275,6 +3382,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default),
// isFocused: false (default)
decoration: const InputDecoration.collapsed(
......@@ -3298,6 +3406,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default),
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -3322,6 +3431,7 @@ void main() {
testWidgets('InputDecorator.collapsed', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default),
// isFocused: false (default)
decoration: const InputDecoration.collapsed(
......@@ -3343,6 +3453,7 @@ void main() {
// The hint should appear
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true,
decoration: const InputDecoration.collapsed(
......@@ -3366,6 +3477,7 @@ void main() {
const TextStyle style = TextStyle(fontFamily: 'Ahem', fontSize: 10.0);
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
baseStyle: style,
decoration: const InputDecoration(
......@@ -3391,19 +3503,20 @@ void main() {
// 10 - label (ahem font size 10dps)
// 17.75 - bottom padding (empty input text still appears here)
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, kMinInteractiveDimension)); // 45.5 bumped up to minimum.
expect(tester.getSize(find.byType(InputDecorator)), Size(800.0, useMaterial3 ? 50.0 : kMinInteractiveDimension)); // 45.5 bumped up to minimum.
expect(tester.getSize(find.text('hint')).height, 10.0);
expect(tester.getSize(find.text('label')).height, 10.0);
expect(tester.getSize(find.text('label')).height, useMaterial3 ? 14.0 : 10.0);
expect(tester.getSize(find.text('text')).height, 10.0);
expect(tester.getTopLeft(find.text('hint')).dy, 24.75);
expect(tester.getTopLeft(find.text('label')).dy, 19.0);
expect(tester.getTopLeft(find.text('text')).dy, 24.75);
expect(tester.getTopLeft(find.text('hint')).dy, useMaterial3 ? 27.25 : 24.75);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 18 : 19.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 24.75);
});
testWidgets('InputDecorator with empty style overrides', (WidgetTester tester) async {
// Same as not specifying any style overrides
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -3432,10 +3545,10 @@ void main() {
// Label is floating because isEmpty is false.
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 76.0));
expect(tester.getTopLeft(find.text('text')).dy, 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, 44.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('text')).dy, useMaterial3 ? 27.25 : 28.0);
expect(tester.getBottomLeft(find.text('text')).dy, useMaterial3 ? 43.25 : 44.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
expect(tester.getTopLeft(find.text('helper')), const Offset(12.0, 64.0));
......@@ -3445,6 +3558,7 @@ void main() {
testWidgets('InputDecoration outline shape with no border and no floating placeholder', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
isEmpty: true,
decoration: const InputDecoration(
......@@ -3460,8 +3574,8 @@ void main() {
// 16 - label (ahem font size 16dps)
// 20 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 0.0);
});
......@@ -3469,6 +3583,7 @@ void main() {
testWidgets('InputDecoration outline shape with no border and no floating placeholder not empty', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -3485,8 +3600,8 @@ void main() {
// 20 - bottom padding
// expect(tester.widget<Text>(find.text('prefix')).style.color, prefixStyle.color);
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 0.0);
......@@ -3518,6 +3633,7 @@ void main() {
testWidgets('InputDecorationTheme outline border', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true, // label appears, vertically centered
// isFocused: false (default)
inputDecorationTheme: const InputDecorationTheme(
......@@ -3534,8 +3650,8 @@ void main() {
// 16 - label (ahem font size 16dps)
// 20 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
});
......@@ -3543,6 +3659,7 @@ void main() {
testWidgets('InputDecorationTheme outline border, dense layout', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true, // label appears, vertically centered
// isFocused: false (default)
inputDecorationTheme: const InputDecorationTheme(
......@@ -3561,18 +3678,18 @@ void main() {
// 16 - label (ahem font size 16dps)
// 16 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 48.0));
expect(tester.getTopLeft(find.text('label')).dy, 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, 32.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 17.0 : 16.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 31.0 : 32.0);
expect(getBorderBottom(tester), 48.0);
expect(getBorderWeight(tester), 1.0);
});
testWidgets('InputDecorationTheme style overrides', (WidgetTester tester) async {
const TextStyle style16 = TextStyle(fontFamily: 'Ahem', fontSize: 16.0);
final TextStyle labelStyle = style16.merge(const TextStyle(color: Colors.red));
final TextStyle hintStyle = style16.merge(const TextStyle(color: Colors.green));
final TextStyle prefixStyle = style16.merge(const TextStyle(color: Colors.blue));
final TextStyle suffixStyle = style16.merge(const TextStyle(color: Colors.purple));
final TextStyle defaultStyle = TextStyle(fontFamily: 'Ahem', fontSize: useMaterial3 ? 14.0 : 16.0);
final TextStyle labelStyle = defaultStyle.merge(const TextStyle(color: Colors.red));
final TextStyle hintStyle = defaultStyle.merge(const TextStyle(color: Colors.green));
final TextStyle prefixStyle = defaultStyle.merge(const TextStyle(color: Colors.blue));
final TextStyle suffixStyle = defaultStyle.merge(const TextStyle(color: Colors.purple));
const TextStyle style12 = TextStyle(fontFamily: 'Ahem', fontSize: 12.0);
final TextStyle helperStyle = style12.merge(const TextStyle(color: Colors.orange));
......@@ -3585,6 +3702,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true, // label appears, vertically centered
// isFocused: false (default)
inputDecorationTheme: InputDecorationTheme(
......@@ -3616,8 +3734,8 @@ void main() {
// 8 - below the border padding
// 12 - help/error/counter text (ahem font size 12dps)
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 76.0));
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0: 36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
expect(tester.getTopLeft(find.text('helper')), const Offset(0.0, 64.0));
......@@ -3633,12 +3751,12 @@ void main() {
});
testWidgets('InputDecorationTheme style overrides (focused)', (WidgetTester tester) async {
const TextStyle style16 = TextStyle(fontFamily: 'Ahem', fontSize: 16.0);
final TextStyle labelStyle = style16.merge(const TextStyle(color: Colors.red));
final TextStyle floatingLabelStyle = style16.merge(const TextStyle(color: Colors.indigo));
final TextStyle hintStyle = style16.merge(const TextStyle(color: Colors.green));
final TextStyle prefixStyle = style16.merge(const TextStyle(color: Colors.blue));
final TextStyle suffixStyle = style16.merge(const TextStyle(color: Colors.purple));
final TextStyle defaultStyle = TextStyle(fontFamily: 'Ahem', fontSize: useMaterial3 ? 14.0 : 16.0);
final TextStyle labelStyle = defaultStyle.merge(const TextStyle(color: Colors.red));
final TextStyle floatingLabelStyle = defaultStyle.merge(const TextStyle(color: Colors.indigo));
final TextStyle hintStyle = defaultStyle.merge(const TextStyle(color: Colors.green));
final TextStyle prefixStyle = defaultStyle.merge(const TextStyle(color: Colors.blue));
final TextStyle suffixStyle = defaultStyle.merge(const TextStyle(color: Colors.purple));
const TextStyle style12 = TextStyle(fontFamily: 'Ahem', fontSize: 12.0);
final TextStyle helperStyle = style12.merge(const TextStyle(color: Colors.orange));
......@@ -3651,6 +3769,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true, // Label appears floating above input field.
inputDecorationTheme: InputDecorationTheme(
......@@ -3683,8 +3802,8 @@ void main() {
// 8 - below the border padding
// 12 - help/error/counter text (ahem font size 12dps)
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 76.0));
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
expect(tester.getTopLeft(find.text('helper')), const Offset(0.0, 64.0));
......@@ -3716,6 +3835,7 @@ void main() {
testWidgets('InputDecorator.debugDescribeChildren', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
icon: Text('icon'),
labelText: 'label',
......@@ -3758,6 +3878,7 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/14165
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -3769,8 +3890,8 @@ void main() {
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(getBorderWeight(tester), 0.0);
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 23.25 : 24.0);
});
testWidgets('InputDecorationTheme.inputDecoration', (WidgetTester tester) async {
......@@ -3978,6 +4099,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -4016,6 +4138,7 @@ void main() {
testWidgets('InputDecorator UnderlineInputBorder fillColor is clipped by border', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
......@@ -4158,10 +4281,10 @@ void main() {
);
testWidgets('InputDecorator draws and animates hoverColor', (WidgetTester tester) async {
const Color fillColor = Color(0x0A000000);
final Color fillColor = useMaterial3 ? const Color(0xffffffff) : const Color(0x0A000000);
const Color hoverColor = Color(0xFF00FF00);
const Color disabledColor = Color(0x05000000);
const Color enabledBorderColor = Color(0x61000000);
final Color disabledColor =useMaterial3 ? const Color(0x0A000000) : const Color(0x05000000);
final Color enabledBorderColor = useMaterial3 ? const Color(0xffffffff) : const Color(0x61000000);
Future<void> pumpDecorator({
required bool hovering,
......@@ -4170,13 +4293,14 @@ void main() {
}) async {
return tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isHovering: hovering,
decoration: InputDecoration(
enabled: enabled,
filled: filled,
hoverColor: hoverColor,
disabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: disabledColor)),
border: const OutlineInputBorder(borderSide: BorderSide(color: enabledBorderColor)),
disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: disabledColor)),
border: OutlineInputBorder(borderSide: BorderSide(color: enabledBorderColor)),
),
),
);
......@@ -4209,7 +4333,7 @@ void main() {
expect(getContainerColor(tester), equals(disabledColor));
// Test outline text field.
const Color blendedHoverColor = Color(0x74004400);
final Color blendedHoverColor = useMaterial3 ? const Color(0xff000000) : const Color(0x74004400);
await pumpDecorator(hovering: false, filled: false);
await tester.pumpAndSettle();
expect(getBorderColor(tester), equals(enabledBorderColor));
......@@ -4240,7 +4364,7 @@ void main() {
testWidgets('InputDecorator draws and animates focusColor', (WidgetTester tester) async {
const Color focusColor = Color(0xFF0000FF);
const Color disabledColor = Color(0x05000000);
const Color enabledBorderColor = Color(0x61000000);
final Color enabledBorderColor = useMaterial3 ? const Color(0xffffffff) : const Color(0x61000000);
Future<void> pumpDecorator({
required bool focused,
......@@ -4249,6 +4373,7 @@ void main() {
}) async {
return tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: focused,
decoration: InputDecoration(
enabled: enabled,
......@@ -4256,7 +4381,7 @@ void main() {
focusColor: focusColor,
focusedBorder: const OutlineInputBorder(borderSide: BorderSide(color: focusColor)),
disabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: disabledColor)),
border: const OutlineInputBorder(borderSide: BorderSide(color: enabledBorderColor)),
border: OutlineInputBorder(borderSide: BorderSide(color: enabledBorderColor)),
),
),
);
......@@ -4300,6 +4425,7 @@ void main() {
}) async {
return tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: empty,
isFocused: focused,
decoration: InputDecoration(
......@@ -4316,44 +4442,45 @@ void main() {
await pumpDecorator(focused: false);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, 20)));
expect(getLabelRect(tester).size, equals(const Size(80, 16)));
final Size labelSize= useMaterial3 ? const Size(70, 14) : const Size(80, 16);
expect(getLabelRect(tester).topLeft, equals(Offset(12, useMaterial3 ? 21 : 20)));
expect(getLabelRect(tester).size, equals(labelSize));
await pumpDecorator(focused: false, empty: false);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, -5.5)));
expect(getLabelRect(tester).size, equals(const Size(80, 16) * 0.75));
expect(getLabelRect(tester).topLeft, equals(Offset(12, useMaterial3 ? -4.75 : -5.5)));
expect(getLabelRect(tester).size, equals(labelSize * 0.75));
await pumpDecorator(focused: true);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, -5.5)));
expect(getLabelRect(tester).size, equals(const Size(80, 16) * 0.75));
expect(getLabelRect(tester).topLeft, equals(Offset(12, useMaterial3 ? -4.75 : -5.5)));
expect(getLabelRect(tester).size, equals(labelSize * 0.75));
await pumpDecorator(focused: true, empty: false);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, -5.5)));
expect(getLabelRect(tester).size, equals(const Size(80, 16) * 0.75));
expect(getLabelRect(tester).topLeft, equals( Offset(12, useMaterial3 ? -4.75 : -5.5)));
expect(getLabelRect(tester).size, equals(labelSize * 0.75));
await pumpDecorator(focused: false, enabled: false);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, 20)));
expect(getLabelRect(tester).size, equals(const Size(80, 16)));
expect(getLabelRect(tester).topLeft, equals(Offset(12, useMaterial3 ? 21 : 20)));
expect(getLabelRect(tester).size, equals(labelSize));
await pumpDecorator(focused: false, empty: false, enabled: false);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, -5.5)));
expect(getLabelRect(tester).size, equals(const Size(80, 16) * 0.75));
expect(getLabelRect(tester).topLeft, equals( Offset(12, useMaterial3 ? -4.75 : -5.5)));
expect(getLabelRect(tester).size, equals(labelSize * 0.75));
// Focused and disabled happens with NavigationMode.directional.
await pumpDecorator(focused: true, enabled: false);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, 20)));
expect(getLabelRect(tester).size, equals(const Size(80, 16)));
expect(getLabelRect(tester).topLeft, equals(Offset(12, useMaterial3 ? 21 : 20)));
expect(getLabelRect(tester).size, equals(labelSize));
await pumpDecorator(focused: true, empty: false, enabled: false);
await tester.pumpAndSettle();
expect(getLabelRect(tester).topLeft, equals(const Offset(12, -5.5)));
expect(getLabelRect(tester).size, equals(const Size(80, 16) * 0.75));
expect(getLabelRect(tester).topLeft, equals( Offset(12, useMaterial3 ? -4.75 : -5.5)));
expect(getLabelRect(tester).size, equals(labelSize * 0.75));
});
testWidgets('InputDecorationTheme.toString()', (WidgetTester tester) async {
......@@ -4410,12 +4537,14 @@ void main() {
testWidgets('InputDecoration default border uses colorScheme', (WidgetTester tester) async {
final ThemeData theme = ThemeData.from(colorScheme: const ColorScheme.light());
final Color enabledColor = theme.colorScheme.onSurface.withOpacity(0.38);
final Color enabledColor = useMaterial3 ? theme.colorScheme.onSurfaceVariant : theme.colorScheme.onSurface.withOpacity(0.38);
final Color disabledColor = useMaterial3 ? theme.colorScheme.onSurface.withOpacity(0.12) : theme.disabledColor;
final Color hoverColor = Color.alphaBlend(theme.hoverColor.withOpacity(0.12), enabledColor);
// Enabled
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: theme,
),
);
......@@ -4425,6 +4554,7 @@ void main() {
// Filled
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: theme,
decoration: const InputDecoration(
filled: true,
......@@ -4432,11 +4562,12 @@ void main() {
),
);
await tester.pumpAndSettle();
expect(getBorderColor(tester), theme.hintColor);
expect(getBorderColor(tester), useMaterial3 ? theme.colorScheme.onSurfaceVariant : theme.hintColor);
// Hovering
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: theme,
isHovering: true,
),
......@@ -4447,6 +4578,7 @@ void main() {
// Focused
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: theme,
isFocused: true,
),
......@@ -4457,6 +4589,7 @@ void main() {
// Error
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: theme,
decoration: const InputDecoration(
errorText: 'Nope',
......@@ -4469,6 +4602,7 @@ void main() {
// Disabled
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: theme,
decoration: const InputDecoration(
enabled: false,
......@@ -4476,11 +4610,12 @@ void main() {
),
);
await tester.pumpAndSettle();
expect(getBorderColor(tester), theme.disabledColor);
expect(getBorderColor(tester), disabledColor);
// Disabled, filled
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
theme: theme,
decoration: const InputDecoration(
enabled: false,
......@@ -4489,7 +4624,7 @@ void main() {
),
);
await tester.pumpAndSettle();
expect(getBorderColor(tester), Colors.transparent);
expect(getBorderColor(tester), useMaterial3 ? theme.colorScheme.onSurface.withOpacity(0.38) : Colors.transparent);
});
testWidgets('InputDecoration borders', (WidgetTester tester) async {
......@@ -4511,6 +4646,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
decoration: const InputDecoration(
// errorText: null (default)
......@@ -4527,6 +4663,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: true,
decoration: const InputDecoration(
// errorText: null (default)
......@@ -4544,6 +4681,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: true,
decoration: const InputDecoration(
errorText: 'error',
......@@ -4561,6 +4699,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
decoration: const InputDecoration(
errorText: 'error',
......@@ -4578,6 +4717,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
decoration: const InputDecoration(
errorText: 'error',
......@@ -4595,6 +4735,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
decoration: const InputDecoration(
// errorText: false (default)
......@@ -4612,6 +4753,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: true,
decoration: const InputDecoration(
// errorText: null (default)
......@@ -4644,6 +4786,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
filled: true,
fillColor: Color(0xFF00FF00),
......@@ -4748,6 +4891,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: InputDecoration(
filled: true,
fillColor: const Color(0xFF00FF00),
......@@ -5036,6 +5180,7 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/54028
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
decoration: const InputDecoration(
labelText: 'label',
......@@ -5051,12 +5196,13 @@ void main() {
// floatingLabelHeight = 12 (ahem font size 16dps * 0.75 = 12)
// labelY = -floatingLabelHeight/2 + borderWidth/2
expect(tester.getTopLeft(find.text('label')).dy, -4.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? -3.25 : -4.0);
});
testWidgets('InputDecorator floating label obeys floatingLabelBehavior', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
decoration: const InputDecoration(
labelText: 'label',
floatingLabelBehavior: FloatingLabelBehavior.never,
......@@ -5066,12 +5212,13 @@ void main() {
// Passing floating behavior never results in a dy offset of 20
// because the label is not initially floating.
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
});
testWidgets('InputDecorator hint is displayed when floatingLabelBehavior is always', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
isEmpty: true,
decoration: const InputDecoration(
......@@ -5096,6 +5243,7 @@ void main() {
width: 100,
height: 100,
child: buildInputDecorator(
useMaterial3: useMaterial3,
// isFocused: false (default)
isEmpty: true,
decoration: InputDecoration(
......@@ -5110,7 +5258,7 @@ void main() {
expect(
find.text(longStringA),
paints..clipRect(rect: const Rect.fromLTWH(0, 0, 100.0, 16.0)),
paints..clipRect(rect: Rect.fromLTWH(0, 0, 100.0, useMaterial3 ? 14.0 : 16.0)),
);
await tester.pumpWidget(
......@@ -5119,6 +5267,7 @@ void main() {
width: 100,
height: 100,
child: buildInputDecorator(
useMaterial3: useMaterial3,
isFocused: true,
isEmpty: true,
decoration: InputDecoration(
......@@ -5134,7 +5283,7 @@ void main() {
expect(
find.text(longStringB),
// 133.3 is approximately 100 / 0.75 (_kFinalLabelScale)
paints..clipRect(rect: const Rect.fromLTWH(0, 0, 133.0, 16.0)),
paints..clipRect(rect: Rect.fromLTWH(0, 0, 133.0, useMaterial3 ? 14.0 : 16.0)),
);
}, skip: isBrowser); // TODO(yjbanov): https://github.com/flutter/flutter/issues/44020
......@@ -5619,6 +5768,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
isFocused: true, // Label appears floating above input field.
inputDecorationTheme: InputDecorationTheme(
......@@ -5640,8 +5790,8 @@ void main() {
// 16 - input text (ahem font size 16dps)
// 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('label')).dy, 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, 24.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 12.75 : 12.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 24.75 : 24.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 2.0);
......@@ -5650,8 +5800,8 @@ void main() {
});
testWidgets('InputDecorationTheme labelStyle overrides label widget styles when the widget is a text widget', (WidgetTester tester) async {
const TextStyle style16 = TextStyle(fontFamily: 'Ahem', fontSize: 16.0);
final TextStyle labelStyle = style16.merge(const TextStyle(color: Colors.purple));
final TextStyle styleDefaultSize = TextStyle(fontFamily: 'Ahem', fontSize: useMaterial3 ? 14.0 : 16.0);
final TextStyle labelStyle = styleDefaultSize.merge(const TextStyle(color: Colors.purple));
// This test also verifies that the default InputDecorator provides a
// "small concession to backwards compatibility" by not padding on
......@@ -5660,6 +5810,7 @@ void main() {
await tester.pumpWidget(
buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true, // Label appears inline, on top of the input field.
inputDecorationTheme: InputDecorationTheme(
labelStyle: labelStyle,
......@@ -5680,8 +5831,8 @@ void main() {
// 16 - input text (ahem font size 16dps)
// 12 - bottom padding
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 56.0));
expect(tester.getTopLeft(find.text('label')).dy, 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, 36.0);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? 21.0 : 20.0);
expect(tester.getBottomLeft(find.text('label')).dy, useMaterial3 ? 35.0 : 36.0);
expect(getBorderBottom(tester), 56.0);
expect(getBorderWeight(tester), 1.0);
......@@ -5692,6 +5843,7 @@ void main() {
testWidgets("InputDecorator's floating label origin no longer depends on ThemeData.fixTextFieldOutlineLabel", (WidgetTester tester) async {
Widget buildFrame(bool fixTextFieldOutlineLabel) {
return buildInputDecorator(
useMaterial3: useMaterial3,
isEmpty: true,
theme: ThemeData.light().copyWith(
fixTextFieldOutlineLabel: fixTextFieldOutlineLabel,
......@@ -5709,11 +5861,12 @@ void main() {
// floatingLabelHeight = 12 (ahem font size 16dps * 0.75 = 12)
// labelY = -floatingLabelHeight/2 + borderWidth/2
expect(tester.getTopLeft(find.text('label')).dy, -5.5);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? -4.75 : -5.5);
await tester.pumpWidget(buildFrame(true));
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text('label')).dy, -5.5);
expect(tester.getTopLeft(find.text('label')).dy, useMaterial3 ? -4.75 : -5.5);
});
}
}
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