Skip to content

Conversation

@bleroux
Copy link
Contributor

@bleroux bleroux commented Jan 7, 2025

Description

This PR changes the TextField intrinsic width computation for non-empty TextField.

Before:

When a TextField is non-empty, the intrinsic width can't be smaller than the hint width:

image

After:

The width does not depend on the hint when the TextField is non empty.

image

Code sample
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Material App',
      home: Scaffold(
        body: Center(
          child: IntrinsicWidth(
            child: TextField(
              decoration: InputDecoration(
                filled: true,
                hintText: 'Moderately long hint text',
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Related Issue

Fixes [TextField] The computation of the intrinsic width of a TextField should include the hint width only when visible

Tests

Adds 2 tests.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Jan 7, 2025
@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch from 0e1aa4e to 9d4aff6 Compare January 7, 2025 15:15
Copy link
Contributor

@nate-thegrate nate-thegrate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, looks like a fantastic improvement overall.

@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch 2 times, most recently from a1e52c1 to bbf2a79 Compare January 10, 2025 09:28
Copy link
Contributor

@nate-thegrate nate-thegrate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the fix!

@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch from bbf2a79 to f356db5 Compare January 13, 2025 05:59
@bleroux
Copy link
Contributor Author

bleroux commented Jan 14, 2025

@justinmc When you have some bandwidth, thank you for having a look at these Google testing failures.

This PR changes the default intrinsic width computation (ignoring the hint width when the field is not empty). Maybe we should consider introducing a new property to control this behavior?

Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good, minus the Google failures. I see three categories of failures:

  1. Expected visual diff changes where a field becomes less wide.
  2. Unexpected visual diff changes in the vertical size of a field.
  3. Unexpected changes in a displayed value in some tests (maybe caused by a misclick due to layout problems from the previous point).

I think I can reproduce the problem from point 2:

Example code
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        body: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 100.0),
            child: const IntrinsicWidth(
              child: TextField(
                maxLines: null,
                decoration: InputDecoration(
                  filled: true,
                  hintText: 'Moderately long hint text',
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
Screen.Recording.2025-01-15.at.2.53.55.PM.mov

@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch 2 times, most recently from c0efcca to 9fd2320 Compare January 16, 2025 14:36
@bleroux
Copy link
Contributor Author

bleroux commented Jan 16, 2025

I updated the PR to fix the failure related to point 2 (see #161235 (review)).
But it breaks some existing test that were assuming that the height should not change whether the hint is visible or not.

As mentioned in #161235 (comment), adding a property to control the behavior is probably safer.
A somewhat recent PR which added such a property, InputDecorator.maintainHintHeight to control the height behavior, see #161235 (review)

Maybe we should deprecate this parameter and create a similar one that would also apply to the width? Such as maintainHintSize?
This parameter would default to true (similarly to InputDecorator.maintainHintHeight) and the width logic change would only apply if this parameter is true.

@justinmc
Copy link
Contributor

Yeah I think I agree with the idea of adding a parameter. The difference is big enough to warrant one, and I do imagine some people might still prefer the old way.

With a parameter, do you plan for it to work like it was when I reviewed it above? With the current state of the PR, it seems like it might affect the height of normal fields too, by looking at the failing Google tests.

@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch 2 times, most recently from f1576ff to e2db406 Compare January 20, 2025 13:41
@bleroux
Copy link
Contributor Author

bleroux commented Jan 20, 2025

With a parameter, do you plan for it to work like it was when I reviewed it above?

No because the height issue was bad

I updated the PR to demonstrate what this parameter solution could be.
The point is to replace the maintainHintHeight with a parameter that control both height and width, I proposed maintainHintSize. This parameter defaults to true to keep the current behavior (text field size can't be less than hint size).
When set to false, the hint will be ignored for both height and width computation when it is not visible (aka when the field is not empty).

@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch 3 times, most recently from e00eba9 to a7cb8c1 Compare January 21, 2025 15:23
Copy link
Contributor

@nate-thegrate nate-thegrate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with 1 small nit. Thanks again for doing this!

@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch from a7cb8c1 to f01d087 Compare January 23, 2025 15:36
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍. All comments are nits. I tried it out and it works great. I definitely agree that adding the parameter is the right move.

if (hintMaxLines != null) 'hintMaxLines: "$hintMaxLines"',
if (hintFadeDuration != null) 'hintFadeDuration: "$hintFadeDuration"',
if (!maintainHintHeight) 'maintainHintHeight: false',
if (!maintainHintSize) 'maintainHintSize: false',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the false be $maintainHintSize? I'm not sure why maintainHintHeight is hardcoded false.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting! I checked and the reason is that this toString implementation was designed to only output fields that don't use their default value. This pattern (hardcoding the non-default boolean value) was introduced in the early days, see #9119. I think it is ok to keep it as-is for this PR and we might decide to change the whole toString at one point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for the investigation!

@bleroux bleroux force-pushed the fix_TextField_intrinsic_width_visible_hint branch from f01d087 to ef1f7e7 Compare January 24, 2025 07:57
@bleroux bleroux added the autosubmit Merge PR when tree becomes green via auto submit App label Jan 24, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Jan 24, 2025
Merged via the queue into flutter:master with commit a2ec056 Jan 24, 2025
99 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jan 24, 2025
@bleroux bleroux deleted the fix_TextField_intrinsic_width_visible_hint branch January 24, 2025 13:42
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 24, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 24, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 24, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 24, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jan 24, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Jan 24, 2025
Manual roll requested by [email protected]

flutter/flutter@c1561a4...c1ffaa9

2025-01-24 [email protected] Fix link to hotfix documentation best practices (flutter/flutter#162116)
2025-01-24 [email protected] Add integration test for cutout rotation evaluation (flutter/flutter#160354)
2025-01-24 [email protected] Reland "[Impeller] Migrate unit tests off of Skia geometry classes (#161855)" (flutter/flutter#162146)
2025-01-24 [email protected] Fix TextField intrinsic width when hint is not visible (flutter/flutter#161235)
2025-01-24 [email protected] When parsing flavors, handle Xcode build configurations that are not lowercase (flutter/flutter#161455)
2025-01-24 [email protected] [Impeller] Fix source offset in PathBuilder::AddPath (flutter/flutter#162052)
2025-01-24 [email protected] Add to Setup Path Example to Engine README (flutter/flutter#162115)
2025-01-23 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Unskip test. (#162106)" (flutter/flutter#162122)
2025-01-23 [email protected] feat: Add `hint` (Widget) property to InputDecoration (flutter/flutter#161424)
2025-01-23 [email protected] Fix skwasm target in wasm_debug_unopt build. (flutter/flutter#162100)
2025-01-23 [email protected] Marks Linux_android_emu android views to be unflaky (flutter/flutter#160493)
2025-01-23 [email protected] Unskip test. (flutter/flutter#162106)
2025-01-23 [email protected] Add ability to maintain bottom view padding in `NavigationBar` safe area (flutter/flutter#162076)
2025-01-23 [email protected] Roll pub packages (flutter/flutter#162095)
2025-01-23 [email protected] Delete an unused (manual) workflow, added missing copyright headers. (flutter/flutter#162050)
2025-01-23 [email protected] Android templates: update default Kotlin from 1.8.22 to 2.1.0, update default Gradle from 8.9 to 8.12 (flutter/flutter#160974)
2025-01-23 [email protected] flutter_tools: flutter_tester is a host artifact (flutter/flutter#162047)
2025-01-23 [email protected] [Impeller] Make glIsTexture mockable for use by the ReactorGLES.NameUntrackedHandle test (flutter/flutter#162082)
2025-01-23 [email protected] Remove "Mac Designed for iPad" as a discoverable `flutter run` device (flutter/flutter#161459)
2025-01-23 [email protected] Show error on macOS if missing Local Network permissions (flutter/flutter#161846)
2025-01-23 [email protected] Autocomplete keyboard navigation (flutter/flutter#159455)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@TiberioZ
Copy link

TiberioZ commented Feb 2, 2025

Is this fixed bug works with CupertinoTextField ? I've tried and it seems not working, maybe I'm doing it wrong...

const IntrinsicWidth(
child: CupertinoTextField(
placeholder: "search",
),
)

@bleroux
Copy link
Contributor Author

bleroux commented Feb 3, 2025

@TiberioZ
This fix applies to InputDecorator which is not used by CupertinoTextField.
If you want a similar feature for the CupertinoTextField, thank you to create a new issue.

github-merge-queue bot pushed a commit that referenced this pull request Feb 5, 2025
## Description

This PR adds a dart fix to migrate from
InputDecoration.maintainHintHeight to InputDecoration.maintainHintSize.

## Related PR

Follow up to #161235

## Tests

Adds 1 test.
antfitch pushed a commit to flutter/website that referenced this pull request Feb 28, 2025
…11742)

This PR adds a migration guide for inputDecoration.maintainHintHeight.

Related PRs:
- flutter/flutter#161235
- dart fix: flutter/flutter#162600

## Presubmit checklist

- [ ] This PR is marked as draft with an explanation if not meant to
land until a future stable release.
- [X] This PR doesn’t contain automatically generated corrections
(Grammarly or similar).
- [X] This PR follows the [Google Developer Documentation Style
Guidelines](https://developers.google.com/style) — for example, it
doesn’t use _i.e._ or _e.g._, and it avoids _I_ and _we_ (first person).
- [X] This PR uses [semantic line
breaks](https://github.com/dart-lang/site-shared/blob/main/doc/writing-for-dart-and-flutter-websites.md#semantic-line-breaks)
of 80 characters or fewer.
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 21, 2025
androidseb pushed a commit to androidseb/packages that referenced this pull request Jun 8, 2025
)

Manual roll requested by [email protected]

flutter/flutter@c1561a4...c1ffaa9

2025-01-24 [email protected] Fix link to hotfix documentation best practices (flutter/flutter#162116)
2025-01-24 [email protected] Add integration test for cutout rotation evaluation (flutter/flutter#160354)
2025-01-24 [email protected] Reland "[Impeller] Migrate unit tests off of Skia geometry classes (#161855)" (flutter/flutter#162146)
2025-01-24 [email protected] Fix TextField intrinsic width when hint is not visible (flutter/flutter#161235)
2025-01-24 [email protected] When parsing flavors, handle Xcode build configurations that are not lowercase (flutter/flutter#161455)
2025-01-24 [email protected] [Impeller] Fix source offset in PathBuilder::AddPath (flutter/flutter#162052)
2025-01-24 [email protected] Add to Setup Path Example to Engine README (flutter/flutter#162115)
2025-01-23 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Unskip test. (#162106)" (flutter/flutter#162122)
2025-01-23 [email protected] feat: Add `hint` (Widget) property to InputDecoration (flutter/flutter#161424)
2025-01-23 [email protected] Fix skwasm target in wasm_debug_unopt build. (flutter/flutter#162100)
2025-01-23 [email protected] Marks Linux_android_emu android views to be unflaky (flutter/flutter#160493)
2025-01-23 [email protected] Unskip test. (flutter/flutter#162106)
2025-01-23 [email protected] Add ability to maintain bottom view padding in `NavigationBar` safe area (flutter/flutter#162076)
2025-01-23 [email protected] Roll pub packages (flutter/flutter#162095)
2025-01-23 [email protected] Delete an unused (manual) workflow, added missing copyright headers. (flutter/flutter#162050)
2025-01-23 [email protected] Android templates: update default Kotlin from 1.8.22 to 2.1.0, update default Gradle from 8.9 to 8.12 (flutter/flutter#160974)
2025-01-23 [email protected] flutter_tools: flutter_tester is a host artifact (flutter/flutter#162047)
2025-01-23 [email protected] [Impeller] Make glIsTexture mockable for use by the ReactorGLES.NameUntrackedHandle test (flutter/flutter#162082)
2025-01-23 [email protected] Remove "Mac Designed for iPad" as a discoverable `flutter run` device (flutter/flutter#161459)
2025-01-23 [email protected] Show error on macOS if missing Local Network permissions (flutter/flutter#161846)
2025-01-23 [email protected] Autocomplete keyboard navigation (flutter/flutter#159455)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
FMorschel pushed a commit to FMorschel/packages that referenced this pull request Jun 9, 2025
)

Manual roll requested by [email protected]

flutter/flutter@c1561a4...c1ffaa9

2025-01-24 [email protected] Fix link to hotfix documentation best practices (flutter/flutter#162116)
2025-01-24 [email protected] Add integration test for cutout rotation evaluation (flutter/flutter#160354)
2025-01-24 [email protected] Reland "[Impeller] Migrate unit tests off of Skia geometry classes (#161855)" (flutter/flutter#162146)
2025-01-24 [email protected] Fix TextField intrinsic width when hint is not visible (flutter/flutter#161235)
2025-01-24 [email protected] When parsing flavors, handle Xcode build configurations that are not lowercase (flutter/flutter#161455)
2025-01-24 [email protected] [Impeller] Fix source offset in PathBuilder::AddPath (flutter/flutter#162052)
2025-01-24 [email protected] Add to Setup Path Example to Engine README (flutter/flutter#162115)
2025-01-23 98614782+auto-submit[bot]@users.noreply.github.com Reverts "Unskip test. (#162106)" (flutter/flutter#162122)
2025-01-23 [email protected] feat: Add `hint` (Widget) property to InputDecoration (flutter/flutter#161424)
2025-01-23 [email protected] Fix skwasm target in wasm_debug_unopt build. (flutter/flutter#162100)
2025-01-23 [email protected] Marks Linux_android_emu android views to be unflaky (flutter/flutter#160493)
2025-01-23 [email protected] Unskip test. (flutter/flutter#162106)
2025-01-23 [email protected] Add ability to maintain bottom view padding in `NavigationBar` safe area (flutter/flutter#162076)
2025-01-23 [email protected] Roll pub packages (flutter/flutter#162095)
2025-01-23 [email protected] Delete an unused (manual) workflow, added missing copyright headers. (flutter/flutter#162050)
2025-01-23 [email protected] Android templates: update default Kotlin from 1.8.22 to 2.1.0, update default Gradle from 8.9 to 8.12 (flutter/flutter#160974)
2025-01-23 [email protected] flutter_tools: flutter_tester is a host artifact (flutter/flutter#162047)
2025-01-23 [email protected] [Impeller] Make glIsTexture mockable for use by the ReactorGLES.NameUntrackedHandle test (flutter/flutter#162082)
2025-01-23 [email protected] Remove "Mac Designed for iPad" as a discoverable `flutter run` device (flutter/flutter#161459)
2025-01-23 [email protected] Show error on macOS if missing Local Network permissions (flutter/flutter#161846)
2025-01-23 [email protected] Autocomplete keyboard navigation (flutter/flutter#159455)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[TextField] The computation of the intrinsic width of a TextField should include the hint width only when visible

4 participants