Skip to content

Commit f4bc9c0

Browse files
blerouxromanejaquez
authored andcommitted
Add InputDecoration.visualDensity and InputDecorationTheme.visualDensity (flutter#166834)
## Description This PR introduces `InputDecoration.visualDensity` and `InputDecorationTheme.visualDensity`. See flutter#166201 (comment) for motivation. ## Related Issue Fixes flutter#166201 ## Tests Adds 8 tests (4 for filled decoration, 4 for outlined decoration).
1 parent 8e8c031 commit f4bc9c0

File tree

2 files changed

+380
-10
lines changed

2 files changed

+380
-10
lines changed

packages/flutter/lib/src/material/input_decorator.dart

Lines changed: 82 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,8 +2257,9 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
22572257
@override
22582258
Widget build(BuildContext context) {
22592259
final ThemeData themeData = Theme.of(context);
2260+
final VisualDensity visualDensity = decoration.visualDensity ?? themeData.visualDensity;
22602261
final InputDecorationTheme defaults =
2261-
Theme.of(context).useMaterial3
2262+
themeData.useMaterial3
22622263
? _InputDecoratorDefaultsM3(context)
22632264
: _InputDecoratorDefaultsM2(context);
22642265
final InputDecorationTheme inputDecorationTheme = themeData.inputDecorationTheme;
@@ -2422,7 +2423,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
24222423
child: ConstrainedBox(
24232424
constraints:
24242425
decoration.prefixIconConstraints ??
2425-
themeData.visualDensity.effectiveConstraints(
2426+
visualDensity.effectiveConstraints(
24262427
const BoxConstraints(
24272428
minWidth: kMinInteractiveDimension,
24282429
minHeight: kMinInteractiveDimension,
@@ -2460,7 +2461,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
24602461
child: ConstrainedBox(
24612462
constraints:
24622463
decoration.suffixIconConstraints ??
2463-
themeData.visualDensity.effectiveConstraints(
2464+
visualDensity.effectiveConstraints(
24642465
const BoxConstraints(
24652466
minWidth: kMinInteractiveDimension,
24662467
minHeight: kMinInteractiveDimension,
@@ -2596,7 +2597,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
25962597
alignLabelWithHint: decoration.alignLabelWithHint ?? false,
25972598
isDense: decoration.isDense,
25982599
isEmpty: isEmpty,
2599-
visualDensity: themeData.visualDensity,
2600+
visualDensity: visualDensity,
26002601
maintainHintSize: maintainHintSize,
26012602
icon: icon,
26022603
input: input,
@@ -2773,6 +2774,7 @@ class InputDecoration {
27732774
this.semanticCounterText,
27742775
this.alignLabelWithHint,
27752776
this.constraints,
2777+
this.visualDensity,
27762778
}) : assert(
27772779
!(label != null && labelText != null),
27782780
'Declaring both label and labelText is not supported.',
@@ -2880,7 +2882,8 @@ class InputDecoration {
28802882
floatingLabelBehavior = floatingLabelBehavior,
28812883
// ignore: prefer_initializing_formals, (can't use initializing formals for a deprecated parameter).
28822884
floatingLabelAlignment = floatingLabelAlignment,
2883-
alignLabelWithHint = false;
2885+
alignLabelWithHint = false,
2886+
visualDensity = null;
28842887

28852888
/// An icon to show before the input field and outside of the decoration's
28862889
/// container.
@@ -3794,6 +3797,32 @@ class InputDecoration {
37943797
/// a default height based on text size.
37953798
final BoxConstraints? constraints;
37963799

3800+
/// Defines how compact the decoration's layout will be.
3801+
///
3802+
/// The vertical aspect of the default or user-specified [contentPadding] is adjusted
3803+
/// automatically based on [visualDensity].
3804+
///
3805+
/// When the visual density is [VisualDensity.compact], the vertical aspect of
3806+
/// [contentPadding] is reduced by 8 pixels.
3807+
///
3808+
/// When the visual density is [VisualDensity.comfortable], the vertical aspect of
3809+
/// [contentPadding] is reduced by 4 pixels.
3810+
///
3811+
/// When the visual density is [VisualDensity.standard] vertical aspect of
3812+
/// [contentPadding] is not changed.
3813+
///
3814+
/// If null, then the ambient [ThemeData.inputDecorationTheme]'s
3815+
/// [InputDecorationTheme.visualDensity] will be used. If that is null then
3816+
/// [ThemeData.visualDensity] will be used.
3817+
///
3818+
/// See also:
3819+
///
3820+
/// * [ThemeData.visualDensity], which specifies the [visualDensity] for all widgets
3821+
/// within a [Theme].
3822+
/// * [InputDecorationTheme.visualDensity], which can override this setting for a
3823+
/// given decorator.
3824+
final VisualDensity? visualDensity;
3825+
37973826
/// Creates a copy of this input decoration with the given fields replaced
37983827
/// by the new values.
37993828
InputDecoration copyWith({
@@ -3853,6 +3882,7 @@ class InputDecoration {
38533882
String? semanticCounterText,
38543883
bool? alignLabelWithHint,
38553884
BoxConstraints? constraints,
3885+
VisualDensity? visualDensity,
38563886
}) {
38573887
return InputDecoration(
38583888
icon: icon ?? this.icon,
@@ -3911,6 +3941,7 @@ class InputDecoration {
39113941
semanticCounterText: semanticCounterText ?? this.semanticCounterText,
39123942
alignLabelWithHint: alignLabelWithHint ?? this.alignLabelWithHint,
39133943
constraints: constraints ?? this.constraints,
3944+
visualDensity: visualDensity ?? this.visualDensity,
39143945
);
39153946
}
39163947

@@ -3955,6 +3986,7 @@ class InputDecoration {
39553986
border: border ?? theme.border,
39563987
alignLabelWithHint: alignLabelWithHint ?? theme.alignLabelWithHint,
39573988
constraints: constraints ?? theme.constraints,
3989+
visualDensity: visualDensity ?? theme.visualDensity,
39583990
);
39593991
}
39603992

@@ -4022,7 +4054,8 @@ class InputDecoration {
40224054
other.enabled == enabled &&
40234055
other.semanticCounterText == semanticCounterText &&
40244056
other.alignLabelWithHint == alignLabelWithHint &&
4025-
other.constraints == constraints;
4057+
other.constraints == constraints &&
4058+
other.visualDensity == visualDensity;
40264059
}
40274060

40284061
@override
@@ -4084,6 +4117,7 @@ class InputDecoration {
40844117
semanticCounterText,
40854118
alignLabelWithHint,
40864119
constraints,
4120+
visualDensity,
40874121
];
40884122
return Object.hashAll(values);
40894123
}
@@ -4143,6 +4177,7 @@ class InputDecoration {
41434177
if (semanticCounterText != null) 'semanticCounterText: $semanticCounterText',
41444178
if (alignLabelWithHint != null) 'alignLabelWithHint: $alignLabelWithHint',
41454179
if (constraints != null) 'constraints: $constraints',
4180+
if (visualDensity != null) 'visualDensity: $visualDensity',
41464181
];
41474182
return 'InputDecoration(${description.join(', ')})';
41484183
}
@@ -4198,6 +4233,7 @@ class InputDecorationTheme with Diagnosticable {
41984233
this.border,
41994234
this.alignLabelWithHint = false,
42004235
this.constraints,
4236+
this.visualDensity,
42014237
});
42024238

42034239
/// {@macro flutter.material.inputDecoration.labelStyle}
@@ -4294,9 +4330,9 @@ class InputDecorationTheme with Diagnosticable {
42944330
/// [InputDecoration.helperText], [InputDecoration.errorText], and
42954331
/// [InputDecoration.counterText].
42964332
///
4297-
/// By default the [contentPadding] reflects [isDense] and the type of the
4298-
/// [border]. If [isCollapsed] is true then [contentPadding] is
4299-
/// [EdgeInsets.zero].
4333+
/// By default the [contentPadding] reflects [visualDensity], [isDense] and
4334+
/// the type of the [border]. If [isCollapsed] is true then [contentPadding]
4335+
/// is [EdgeInsets.zero].
43004336
final EdgeInsetsGeometry? contentPadding;
43014337

43024338
/// Whether the decoration is the same size as the input field.
@@ -4612,6 +4648,30 @@ class InputDecorationTheme with Diagnosticable {
46124648
/// given decorator.
46134649
final BoxConstraints? constraints;
46144650

4651+
/// Defines how compact the decoration's layout will be.
4652+
///
4653+
/// The vertical aspect of the default or user-specified [contentPadding] is adjusted
4654+
/// automatically based on [visualDensity].
4655+
///
4656+
/// When the visual density is [VisualDensity.compact], the vertical aspect of
4657+
/// [contentPadding] is reduced by 8 pixels.
4658+
///
4659+
/// When the visual density is [VisualDensity.comfortable], the vertical aspect of
4660+
/// [contentPadding] is reduced by 4 pixels.
4661+
///
4662+
/// When the visual density is [VisualDensity.standard] vertical aspect of
4663+
/// [contentPadding] is not changed.
4664+
///
4665+
/// If null, defaults to [ThemeData.visualDensity].
4666+
///
4667+
/// See also:
4668+
///
4669+
/// * [ThemeData.visualDensity], which specifies the [visualDensity] for all widgets
4670+
/// within a [Theme].
4671+
/// * [InputDecoration.visualDensity], which can override this setting for a
4672+
/// given decorator.
4673+
final VisualDensity? visualDensity;
4674+
46154675
/// Creates a copy of this object but with the given fields replaced with the
46164676
/// new values.
46174677
InputDecorationTheme copyWith({
@@ -4651,6 +4711,7 @@ class InputDecorationTheme with Diagnosticable {
46514711
InputBorder? border,
46524712
bool? alignLabelWithHint,
46534713
BoxConstraints? constraints,
4714+
VisualDensity? visualDensity,
46544715
}) {
46554716
return InputDecorationTheme(
46564717
labelStyle: labelStyle ?? this.labelStyle,
@@ -4689,6 +4750,7 @@ class InputDecorationTheme with Diagnosticable {
46894750
border: border ?? this.border,
46904751
alignLabelWithHint: alignLabelWithHint ?? this.alignLabelWithHint,
46914752
constraints: constraints ?? this.constraints,
4753+
visualDensity: visualDensity ?? this.visualDensity,
46924754
);
46934755
}
46944756

@@ -4736,6 +4798,7 @@ class InputDecorationTheme with Diagnosticable {
47364798
enabledBorder: enabledBorder ?? inputDecorationTheme.enabledBorder,
47374799
border: border ?? inputDecorationTheme.border,
47384800
constraints: constraints ?? inputDecorationTheme.constraints,
4801+
visualDensity: visualDensity ?? inputDecorationTheme.visualDensity,
47394802
);
47404803
}
47414804

@@ -4778,6 +4841,7 @@ class InputDecorationTheme with Diagnosticable {
47784841
alignLabelWithHint,
47794842
constraints,
47804843
hintFadeDuration,
4844+
visualDensity,
47814845
),
47824846
);
47834847

@@ -4826,7 +4890,8 @@ class InputDecorationTheme with Diagnosticable {
48264890
other.hintMaxLines == hintMaxLines &&
48274891
other.alignLabelWithHint == alignLabelWithHint &&
48284892
other.constraints == constraints &&
4829-
other.disabledBorder == disabledBorder;
4893+
other.disabledBorder == disabledBorder &&
4894+
other.visualDensity == visualDensity;
48304895
}
48314896

48324897
@override
@@ -5029,6 +5094,13 @@ class InputDecorationTheme with Diagnosticable {
50295094
defaultValue: defaultTheme.constraints,
50305095
),
50315096
);
5097+
properties.add(
5098+
DiagnosticsProperty<VisualDensity>(
5099+
'visualDensity',
5100+
visualDensity,
5101+
defaultValue: defaultTheme.visualDensity,
5102+
),
5103+
);
50325104
}
50335105
}
50345106

0 commit comments

Comments
 (0)