Unverified Commit 89ff794a authored by Shi-Hao Hong's avatar Shi-Hao Hong Committed by GitHub

InputDecorator prefixIconConstraints and suffixIconConstraints (#50058)

parent 8aa67610
...@@ -1923,7 +1923,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -1923,7 +1923,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
InputDecoration _effectiveDecoration; InputDecoration _effectiveDecoration;
InputDecoration get decoration { InputDecoration get decoration {
_effectiveDecoration ??= widget.decoration.applyDefaults( _effectiveDecoration ??= widget.decoration.applyDefaults(
Theme.of(context).inputDecorationTheme Theme.of(context).inputDecorationTheme,
); );
return _effectiveDecoration; return _effectiveDecoration;
} }
...@@ -2200,7 +2200,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -2200,7 +2200,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
widthFactor: 1.0, widthFactor: 1.0,
heightFactor: 1.0, heightFactor: 1.0,
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints( constraints: decoration.prefixIconConstraints ?? const BoxConstraints(
minWidth: kMinInteractiveDimension, minWidth: kMinInteractiveDimension,
minHeight: kMinInteractiveDimension, minHeight: kMinInteractiveDimension,
), ),
...@@ -2219,7 +2219,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat ...@@ -2219,7 +2219,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
widthFactor: 1.0, widthFactor: 1.0,
heightFactor: 1.0, heightFactor: 1.0,
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints( constraints: decoration.suffixIconConstraints ?? const BoxConstraints(
minWidth: kMinInteractiveDimension, minWidth: kMinInteractiveDimension,
minHeight: kMinInteractiveDimension, minHeight: kMinInteractiveDimension,
), ),
...@@ -2463,6 +2463,7 @@ class InputDecoration { ...@@ -2463,6 +2463,7 @@ class InputDecoration {
this.isDense, this.isDense,
this.contentPadding, this.contentPadding,
this.prefixIcon, this.prefixIcon,
this.prefixIconConstraints,
this.prefix, this.prefix,
this.prefixText, this.prefixText,
this.prefixStyle, this.prefixStyle,
...@@ -2470,6 +2471,7 @@ class InputDecoration { ...@@ -2470,6 +2471,7 @@ class InputDecoration {
this.suffix, this.suffix,
this.suffixText, this.suffixText,
this.suffixStyle, this.suffixStyle,
this.suffixIconConstraints,
this.counter, this.counter,
this.counterText, this.counterText,
this.counterStyle, this.counterStyle,
...@@ -2533,10 +2535,12 @@ class InputDecoration { ...@@ -2533,10 +2535,12 @@ class InputDecoration {
prefix = null, prefix = null,
prefixText = null, prefixText = null,
prefixStyle = null, prefixStyle = null,
prefixIconConstraints = null,
suffix = null, suffix = null,
suffixIcon = null, suffixIcon = null,
suffixText = null, suffixText = null,
suffixStyle = null, suffixStyle = null,
suffixIconConstraints = null,
counter = null, counter = null,
counterText = null, counterText = null,
counterStyle = null, counterStyle = null,
...@@ -2754,6 +2758,58 @@ class InputDecoration { ...@@ -2754,6 +2758,58 @@ class InputDecoration {
/// * [suffixIcon], which is the same but on the trailing edge. /// * [suffixIcon], which is the same but on the trailing edge.
final Widget prefixIcon; final Widget prefixIcon;
/// The constraints for the prefix icon.
///
/// This can be used to modify the [BoxConstraints] surrounding [prefixIcon].
///
/// This property is particularly useful for getting the decoration's height
/// less than 48px. This can be achieved by setting [isDense] to true and
/// setting the constraints' minimum height and width to a value lower than
/// 48px.
///
/// {@tool dartpad --template=stateless_widget_scaffold}
/// This example shows the differences between two `TextField` widgets when
/// [prefixIconConstraints] is set to the default value and when one is not.
///
/// Note that [isDense] must be set to true to be able to
/// set the constraints smaller than 48px.
///
/// If null, [BoxConstraints] with a minimum width and height of 48px is
/// used.
///
/// ```dart
/// Widget build(BuildContext context) {
/// return Padding(
/// padding: const EdgeInsets.symmetric(horizontal: 8.0),
/// child: Column(
/// mainAxisAlignment: MainAxisAlignment.center,
/// children: <Widget>[
/// TextField(
/// decoration: InputDecoration(
/// hintText: 'Normal Icon Constraints',
/// prefixIcon: Icon(Icons.search),
/// ),
/// ),
/// SizedBox(height: 10),
/// TextField(
/// decoration: InputDecoration(
/// isDense: true,
/// hintText:'Smaller Icon Constraints',
/// prefixIcon: Icon(Icons.search),
/// prefixIconConstraints: BoxConstraints(
/// minHeight: 32,
/// minWidth: 32,
/// ),
/// ),
/// ),
/// ],
/// ),
/// );
/// }
/// ```
/// {@end-tool}
final BoxConstraints prefixIconConstraints;
/// Optional widget to place on the line before the input. /// Optional widget to place on the line before the input.
/// ///
/// This can be used, for example, to add some padding to text that would /// This can be used, for example, to add some padding to text that would
...@@ -2867,6 +2923,61 @@ class InputDecoration { ...@@ -2867,6 +2923,61 @@ class InputDecoration {
/// * [prefixStyle], the equivalent but on the leading edge. /// * [prefixStyle], the equivalent but on the leading edge.
final TextStyle suffixStyle; final TextStyle suffixStyle;
/// The constraints for the suffix icon.
///
/// This can be used to modify the [BoxConstraints] surrounding [suffixIcon].
///
/// This property is particularly useful for getting the decoration's height
/// less than 48px. This can be achieved by setting [isDense] to true and
/// setting the constraints' minimum height and width to a value lower than
/// 48px.
///
/// If null, a [BoxConstraints] with a minimum width and height of 48px is
/// used.
///
/// {@tool dartpad --template=stateless_widget_scaffold}
/// This example shows the differences between two `TextField` widgets when
/// [suffixIconConstraints] is set to the default value and when one is not.
///
/// Note that [isDense] must be set to true to be able to
/// set the constraints smaller than 48px.
///
/// If null, [BoxConstraints] with a minimum width and height of 48px is
/// used.
///
/// ```dart
/// Widget build(BuildContext context) {
/// return Padding(
/// padding: const EdgeInsets.symmetric(horizontal: 8.0),
/// child: Column(
/// mainAxisAlignment: MainAxisAlignment.center,
/// children: <Widget>[
/// TextField(
/// decoration: InputDecoration(
/// hintText: 'Normal Icon Constraints',
/// suffixIcon: Icon(Icons.search),
/// ),
/// ),
/// SizedBox(height: 10),
/// TextField(
/// decoration: InputDecoration(
/// isDense: true,
/// hintText:'Smaller Icon Constraints',
/// suffixIcon: Icon(Icons.search),
/// suffixIconConstraints: BoxConstraints(
/// minHeight: 32,
/// minWidth: 32,
/// ),
/// ),
/// ),
/// ],
/// ),
/// );
/// }
/// ```
/// {@end-tool}
final BoxConstraints suffixIconConstraints;
/// Optional text to place below the line as a character count. /// Optional text to place below the line as a character count.
/// ///
/// Rendered using [counterStyle]. Uses [helperStyle] if [counterStyle] is /// Rendered using [counterStyle]. Uses [helperStyle] if [counterStyle] is
...@@ -3151,11 +3262,13 @@ class InputDecoration { ...@@ -3151,11 +3262,13 @@ class InputDecoration {
Widget prefixIcon, Widget prefixIcon,
Widget prefix, Widget prefix,
String prefixText, String prefixText,
BoxConstraints prefixIconConstraints,
TextStyle prefixStyle, TextStyle prefixStyle,
Widget suffixIcon, Widget suffixIcon,
Widget suffix, Widget suffix,
String suffixText, String suffixText,
TextStyle suffixStyle, TextStyle suffixStyle,
BoxConstraints suffixIconConstraints,
Widget counter, Widget counter,
String counterText, String counterText,
TextStyle counterStyle, TextStyle counterStyle,
...@@ -3195,10 +3308,12 @@ class InputDecoration { ...@@ -3195,10 +3308,12 @@ class InputDecoration {
prefix: prefix ?? this.prefix, prefix: prefix ?? this.prefix,
prefixText: prefixText ?? this.prefixText, prefixText: prefixText ?? this.prefixText,
prefixStyle: prefixStyle ?? this.prefixStyle, prefixStyle: prefixStyle ?? this.prefixStyle,
prefixIconConstraints: prefixIconConstraints ?? this.prefixIconConstraints,
suffixIcon: suffixIcon ?? this.suffixIcon, suffixIcon: suffixIcon ?? this.suffixIcon,
suffix: suffix ?? this.suffix, suffix: suffix ?? this.suffix,
suffixText: suffixText ?? this.suffixText, suffixText: suffixText ?? this.suffixText,
suffixStyle: suffixStyle ?? this.suffixStyle, suffixStyle: suffixStyle ?? this.suffixStyle,
suffixIconConstraints: suffixIconConstraints ?? this.suffixIconConstraints,
counter: counter ?? this.counter, counter: counter ?? this.counter,
counterText: counterText ?? this.counterText, counterText: counterText ?? this.counterText,
counterStyle: counterStyle ?? this.counterStyle, counterStyle: counterStyle ?? this.counterStyle,
...@@ -3282,10 +3397,12 @@ class InputDecoration { ...@@ -3282,10 +3397,12 @@ class InputDecoration {
&& other.prefix == prefix && other.prefix == prefix
&& other.prefixText == prefixText && other.prefixText == prefixText
&& other.prefixStyle == prefixStyle && other.prefixStyle == prefixStyle
&& other.prefixIconConstraints == prefixIconConstraints
&& other.suffixIcon == suffixIcon && other.suffixIcon == suffixIcon
&& other.suffix == suffix && other.suffix == suffix
&& other.suffixText == suffixText && other.suffixText == suffixText
&& other.suffixStyle == suffixStyle && other.suffixStyle == suffixStyle
&& other.suffixIconConstraints == suffixIconConstraints
&& other.counter == counter && other.counter == counter
&& other.counterText == counterText && other.counterText == counterText
&& other.counterStyle == counterStyle && other.counterStyle == counterStyle
...@@ -3334,10 +3451,12 @@ class InputDecoration { ...@@ -3334,10 +3451,12 @@ class InputDecoration {
prefix, prefix,
prefixText, prefixText,
prefixStyle, prefixStyle,
prefixIconConstraints,
suffixIcon, suffixIcon,
suffix, suffix,
suffixText, suffixText,
suffixStyle, suffixStyle,
suffixIconConstraints,
counter, counter,
counterText, counterText,
counterStyle, counterStyle,
...@@ -3376,10 +3495,12 @@ class InputDecoration { ...@@ -3376,10 +3495,12 @@ class InputDecoration {
if (prefix != null) 'prefix: $prefix', if (prefix != null) 'prefix: $prefix',
if (prefixText != null) 'prefixText: $prefixText', if (prefixText != null) 'prefixText: $prefixText',
if (prefixStyle != null) 'prefixStyle: $prefixStyle', if (prefixStyle != null) 'prefixStyle: $prefixStyle',
if (prefixIconConstraints != null) 'prefixIconConstraints: $prefixIconConstraints',
if (suffixIcon != null) 'suffixIcon: $suffixIcon', if (suffixIcon != null) 'suffixIcon: $suffixIcon',
if (suffix != null) 'suffix: $suffix', if (suffix != null) 'suffix: $suffix',
if (suffixText != null) 'suffixText: $suffixText', if (suffixText != null) 'suffixText: $suffixText',
if (suffixStyle != null) 'suffixStyle: $suffixStyle', if (suffixStyle != null) 'suffixStyle: $suffixStyle',
if (suffixIconConstraints != null) 'suffixIconConstraints: $suffixIconConstraints',
if (counter != null) 'counter: $counter', if (counter != null) 'counter: $counter',
if (counterText != null) 'counterText: $counterText', if (counterText != null) 'counterText: $counterText',
if (counterStyle != null) 'counterStyle: $counterStyle', if (counterStyle != null) 'counterStyle: $counterStyle',
......
...@@ -1433,6 +1433,43 @@ void main() { ...@@ -1433,6 +1433,43 @@ void main() {
expect(tester.getTopRight(find.text('text')).dx, lessThanOrEqualTo(tester.getTopLeft(find.byIcon(Icons.satellite)).dx)); expect(tester.getTopRight(find.text('text')).dx, lessThanOrEqualTo(tester.getTopLeft(find.byIcon(Icons.satellite)).dx));
}); });
testWidgets('InputDecorator prefixIconConstraints/suffixIconConstraints', (WidgetTester tester) async {
await tester.pumpWidget(
buildInputDecorator(
// isEmpty: false (default)
// isFocused: false (default)
decoration: const InputDecoration(
prefixIcon: Icon(Icons.pages),
prefixIconConstraints: BoxConstraints(
minWidth: 32,
minHeight: 32,
),
suffixIcon: Icon(Icons.satellite),
suffixIconConstraints: BoxConstraints(
minWidth: 25,
minHeight: 25,
),
isDense: true, // has to be true to go below 48px height
),
),
);
// Overall height for this InputDecorator is 32px because the prefix icon
// is now a custom value
expect(tester.getSize(find.byType(InputDecorator)), const Size(800.0, 32.0));
expect(tester.getSize(find.text('text')).height, 16.0);
expect(tester.getSize(find.byIcon(Icons.pages)).height, 32.0);
expect(tester.getSize(find.byIcon(Icons.satellite)).height, 25.0);
// (InputDecorator height - Text widget height) / 2
expect(tester.getTopLeft(find.text('text')).dy, (32.0 - 16.0) / 2);
// prefixIcon should take up the entire height of InputDecorator
expect(tester.getTopLeft(find.byIcon(Icons.pages)).dy, 0.0);
// (InputDecorator height - suffixIcon height) / 2
expect(tester.getTopLeft(find.byIcon(Icons.satellite)).dy, (32.0 - 25.0) / 2);
expect(tester.getTopRight(find.byIcon(Icons.satellite)).dx, 800.0);
});
testWidgets('prefix/suffix icons are centered when smaller than 48 by 48', (WidgetTester tester) async { testWidgets('prefix/suffix icons are centered when smaller than 48 by 48', (WidgetTester tester) async {
const Key prefixKey = Key('prefix'); const Key prefixKey = Key('prefix');
await tester.pumpWidget( await tester.pumpWidget(
......
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