Added the ability to constrain the size of input decorators (#80754)
This commit is contained in:
parent
5526dcc24b
commit
07a6b8f071
@ -2363,7 +2363,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
: const EdgeInsets.fromLTRB(12.0, 24.0, 12.0, 16.0));
|
||||
}
|
||||
|
||||
return _Decorator(
|
||||
final _Decorator decorator = _Decorator(
|
||||
decoration: _Decoration(
|
||||
contentPadding: contentPadding,
|
||||
isCollapsed: decoration!.isCollapsed,
|
||||
@ -2393,6 +2393,15 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
|
||||
isFocused: isFocused,
|
||||
expands: widget.expands,
|
||||
);
|
||||
|
||||
final BoxConstraints? constraints = decoration!.constraints ?? themeData.inputDecorationTheme.constraints;
|
||||
if (constraints != null) {
|
||||
return ConstrainedBox(
|
||||
constraints: constraints,
|
||||
child: decorator,
|
||||
);
|
||||
}
|
||||
return decorator;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2563,6 +2572,7 @@ class InputDecoration {
|
||||
this.enabled = true,
|
||||
this.semanticCounterText,
|
||||
this.alignLabelWithHint,
|
||||
this.constraints,
|
||||
}) : assert(enabled != null),
|
||||
assert(!(prefix != null && prefixText != null), 'Declaring both prefix and prefixText is not supported.'),
|
||||
assert(!(suffix != null && suffixText != null), 'Declaring both suffix and suffixText is not supported.');
|
||||
@ -2625,7 +2635,8 @@ class InputDecoration {
|
||||
disabledBorder = null,
|
||||
enabledBorder = null,
|
||||
semanticCounterText = null,
|
||||
alignLabelWithHint = false;
|
||||
alignLabelWithHint = false,
|
||||
constraints = null;
|
||||
|
||||
/// An icon to show before the input field and outside of the decoration's
|
||||
/// container.
|
||||
@ -3320,6 +3331,20 @@ class InputDecoration {
|
||||
/// Defaults to false.
|
||||
final bool? alignLabelWithHint;
|
||||
|
||||
/// Defines minimum and maximum sizes for the [InputDecorator].
|
||||
///
|
||||
/// Typically the decorator will fill the horizontal space it is given. For
|
||||
/// larger screens, it may be useful to have the maximum width clamped to
|
||||
/// a given value so it doesn't fill the whole screen. This property
|
||||
/// allows you to control how big the decorator will be in its available
|
||||
/// space.
|
||||
///
|
||||
/// If null, then the ambient [ThemeData.inputDecorationTheme]'s
|
||||
/// [InputDecorationTheme.constraints] will be used. If that
|
||||
/// is null then the decorator will fill the available width with
|
||||
/// a default height based on text size.
|
||||
final BoxConstraints? constraints;
|
||||
|
||||
/// Creates a copy of this input decoration with the given fields replaced
|
||||
/// by the new values.
|
||||
InputDecoration copyWith({
|
||||
@ -3367,6 +3392,7 @@ class InputDecoration {
|
||||
bool? enabled,
|
||||
String? semanticCounterText,
|
||||
bool? alignLabelWithHint,
|
||||
BoxConstraints? constraints,
|
||||
}) {
|
||||
return InputDecoration(
|
||||
icon: icon ?? this.icon,
|
||||
@ -3413,6 +3439,7 @@ class InputDecoration {
|
||||
enabled: enabled ?? this.enabled,
|
||||
semanticCounterText: semanticCounterText ?? this.semanticCounterText,
|
||||
alignLabelWithHint: alignLabelWithHint ?? this.alignLabelWithHint,
|
||||
constraints: constraints ?? this.constraints,
|
||||
);
|
||||
}
|
||||
|
||||
@ -3448,6 +3475,7 @@ class InputDecoration {
|
||||
enabledBorder: enabledBorder ?? theme.enabledBorder,
|
||||
border: border ?? theme.border,
|
||||
alignLabelWithHint: alignLabelWithHint ?? theme.alignLabelWithHint,
|
||||
constraints: constraints ?? theme.constraints,
|
||||
);
|
||||
}
|
||||
|
||||
@ -3501,7 +3529,8 @@ class InputDecoration {
|
||||
&& other.border == border
|
||||
&& other.enabled == enabled
|
||||
&& other.semanticCounterText == semanticCounterText
|
||||
&& other.alignLabelWithHint == alignLabelWithHint;
|
||||
&& other.alignLabelWithHint == alignLabelWithHint
|
||||
&& other.constraints == constraints;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -3553,6 +3582,7 @@ class InputDecoration {
|
||||
enabled,
|
||||
semanticCounterText,
|
||||
alignLabelWithHint,
|
||||
constraints,
|
||||
];
|
||||
return hashList(values);
|
||||
}
|
||||
@ -3600,6 +3630,7 @@ class InputDecoration {
|
||||
if (!enabled) 'enabled: false',
|
||||
if (semanticCounterText != null) 'semanticCounterText: $semanticCounterText',
|
||||
if (alignLabelWithHint != null) 'alignLabelWithHint: $alignLabelWithHint',
|
||||
if (constraints != null) 'constraints: $constraints',
|
||||
];
|
||||
return 'InputDecoration(${description.join(', ')})';
|
||||
}
|
||||
@ -3651,6 +3682,7 @@ class InputDecorationTheme with Diagnosticable {
|
||||
this.enabledBorder,
|
||||
this.border,
|
||||
this.alignLabelWithHint = false,
|
||||
this.constraints,
|
||||
}) : assert(isDense != null),
|
||||
assert(isCollapsed != null),
|
||||
assert(filled != null),
|
||||
@ -3972,6 +4004,23 @@ class InputDecorationTheme with Diagnosticable {
|
||||
/// behavior of aligning the label with the center of the [TextField].
|
||||
final bool alignLabelWithHint;
|
||||
|
||||
/// Defines minimum and maximum sizes for the [InputDecorator].
|
||||
///
|
||||
/// Typically the decorator will fill the horizontal space it is given. For
|
||||
/// larger screens, it may be useful to have the maximum width clamped to
|
||||
/// a given value so it doesn't fill the whole screen. This property
|
||||
/// allows you to control how big the decorator will be in its available
|
||||
/// space.
|
||||
///
|
||||
/// If null, then the decorator will fill the available width with
|
||||
/// a default height based on text size.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [InputDecoration.constraints], which can override this setting for a
|
||||
/// given decorator.
|
||||
final BoxConstraints? constraints;
|
||||
|
||||
/// Creates a copy of this object but with the given fields replaced with the
|
||||
/// new values.
|
||||
InputDecorationTheme copyWith({
|
||||
@ -4004,6 +4053,7 @@ class InputDecorationTheme with Diagnosticable {
|
||||
InputBorder? enabledBorder,
|
||||
InputBorder? border,
|
||||
bool? alignLabelWithHint,
|
||||
BoxConstraints? constraints,
|
||||
}) {
|
||||
return InputDecorationTheme(
|
||||
labelStyle: labelStyle ?? this.labelStyle,
|
||||
@ -4031,6 +4081,7 @@ class InputDecorationTheme with Diagnosticable {
|
||||
enabledBorder: enabledBorder ?? this.enabledBorder,
|
||||
border: border ?? this.border,
|
||||
alignLabelWithHint: alignLabelWithHint ?? this.alignLabelWithHint,
|
||||
constraints: constraints ?? this.constraints,
|
||||
);
|
||||
}
|
||||
|
||||
@ -4062,6 +4113,7 @@ class InputDecorationTheme with Diagnosticable {
|
||||
enabledBorder,
|
||||
border,
|
||||
alignLabelWithHint,
|
||||
constraints,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -4096,6 +4148,7 @@ class InputDecorationTheme with Diagnosticable {
|
||||
&& other.enabledBorder == enabledBorder
|
||||
&& other.border == border
|
||||
&& other.alignLabelWithHint == alignLabelWithHint
|
||||
&& other.constraints == constraints
|
||||
&& other.disabledBorder == disabledBorder;
|
||||
}
|
||||
|
||||
@ -4128,5 +4181,6 @@ class InputDecorationTheme with Diagnosticable {
|
||||
properties.add(DiagnosticsProperty<InputBorder>('enabledBorder', enabledBorder, defaultValue: defaultTheme.enabledBorder));
|
||||
properties.add(DiagnosticsProperty<InputBorder>('border', border, defaultValue: defaultTheme.border));
|
||||
properties.add(DiagnosticsProperty<bool>('alignLabelWithHint', alignLabelWithHint, defaultValue: defaultTheme.alignLabelWithHint));
|
||||
properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: defaultTheme.constraints));
|
||||
}
|
||||
}
|
||||
|
@ -1728,6 +1728,49 @@ void main() {
|
||||
expect(tester.getTopLeft(find.byKey(prefixKey)).dy, 0.0);
|
||||
});
|
||||
|
||||
group('constraints', () {
|
||||
testWidgets('No InputDecorator constraints', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(buildInputDecorator());
|
||||
|
||||
// Should fill the screen width and be default height
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(800, 48));
|
||||
});
|
||||
|
||||
testWidgets('InputDecoratorThemeData constraints', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
theme: ThemeData(
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
constraints: BoxConstraints(maxWidth: 300, maxHeight: 40),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Theme settings should make it 300x40 pixels
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(300, 40));
|
||||
});
|
||||
|
||||
testWidgets('InputDecorator constraints', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
buildInputDecorator(
|
||||
theme: ThemeData(
|
||||
inputDecorationTheme: const InputDecorationTheme(
|
||||
constraints: BoxConstraints(maxWidth: 300, maxHeight: 40),
|
||||
),
|
||||
),
|
||||
decoration: const InputDecoration(
|
||||
constraints: BoxConstraints(maxWidth: 200, maxHeight: 32),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// InputDecoration.constraints should override the theme. It should be
|
||||
// only 200x32 pixels
|
||||
expect(tester.getSize(find.byType(InputDecorator)), const Size(200, 32));
|
||||
});
|
||||
});
|
||||
|
||||
group('textAlignVertical position', () {
|
||||
group('simple case', () {
|
||||
testWidgets('align top (default)', (WidgetTester tester) async {
|
||||
@ -3139,6 +3182,7 @@ void main() {
|
||||
focusColor: Colors.blue,
|
||||
border: InputBorder.none,
|
||||
alignLabelWithHint: true,
|
||||
constraints: BoxConstraints(minWidth: 10, maxWidth: 20, minHeight: 30, maxHeight: 40),
|
||||
),
|
||||
);
|
||||
|
||||
@ -3155,6 +3199,7 @@ void main() {
|
||||
expect(decoration.fillColor, Colors.red);
|
||||
expect(decoration.border, InputBorder.none);
|
||||
expect(decoration.alignLabelWithHint, true);
|
||||
expect(decoration.constraints, const BoxConstraints(minWidth: 10, maxWidth: 20, minHeight: 30, maxHeight: 40));
|
||||
|
||||
// InputDecoration (baseDecoration) defines InputDecoration properties
|
||||
decoration = const InputDecoration(
|
||||
@ -3171,6 +3216,7 @@ void main() {
|
||||
fillColor: Colors.blue,
|
||||
border: OutlineInputBorder(),
|
||||
alignLabelWithHint: false,
|
||||
constraints: BoxConstraints(minWidth: 10, maxWidth: 20, minHeight: 30, maxHeight: 40),
|
||||
).applyDefaults(
|
||||
const InputDecorationTheme(
|
||||
labelStyle: themeStyle,
|
||||
@ -3189,6 +3235,7 @@ void main() {
|
||||
focusColor: Colors.blue,
|
||||
border: InputBorder.none,
|
||||
alignLabelWithHint: true,
|
||||
constraints: BoxConstraints(minWidth: 40, maxWidth: 30, minHeight: 20, maxHeight: 10),
|
||||
),
|
||||
);
|
||||
|
||||
@ -3207,6 +3254,7 @@ void main() {
|
||||
expect(decoration.fillColor, Colors.blue);
|
||||
expect(decoration.border, const OutlineInputBorder());
|
||||
expect(decoration.alignLabelWithHint, false);
|
||||
expect(decoration.constraints, const BoxConstraints(minWidth: 10, maxWidth: 20, minHeight: 30, maxHeight: 40));
|
||||
});
|
||||
|
||||
testWidgets('InputDecorator OutlineInputBorder fillColor is clipped by border', (WidgetTester tester) async {
|
||||
|
Loading…
x
Reference in New Issue
Block a user