Skip to content

Conversation

@bleroux
Copy link
Contributor

@bleroux bleroux commented Feb 13, 2025

Description

This PR fixes DropdownButtonFormField suffix icon vertical alignment when DropdownButtonFormField.inputDecoration is provided without a hint text.

Before:

The dropdown icon is misaligned vertically:

image

After:

The dropdown icon is aligned vertically:

image

Related Issue

Fixes DropdownButtonFormField arrow icon is misaligned vertically

Tests

Adds 1 test.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Feb 13, 2025
@bleroux bleroux force-pushed the fix_dropdown_button_form_field_icon_not_vertically_centered branch 3 times, most recently from 3b28af6 to 955fb0b Compare February 13, 2025 13:27
@bleroux bleroux requested a review from justinmc February 13, 2025 18:34
@bleroux
Copy link
Contributor Author

bleroux commented Feb 13, 2025

@justinmc This PR replaces #159328 as the workaround that was used in #159328 is no more needed since #159975 was merged.

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.

It's really good that #159975 simplified the solution here.

LGTM but let's see if the Google tests pass.

@bleroux bleroux force-pushed the fix_dropdown_button_form_field_icon_not_vertically_centered branch from 955fb0b to 4d79b7a Compare February 27, 2025 08:09
InputDecoration effectiveDecoration = widget._inputDecoration!.copyWith(
// Override the suffix icon constraints to allow the
// icon alignment to match the regular dropdown button.
suffixIconConstraints: const BoxConstraints(minWidth: 40.0),
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like there are some Google failures where some text that used to fit inside of the dropdown no longer fits, as if the horizontal space available in the field has been reduced. Is that due to this minWidth constraints change? Is that horizontal space change intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, interesting!

as if the horizontal space available in the field has been reduced

I don't remember why we choose to set the minWidth to 40.0. Maybe something from a previous version of the PR.
I updated the PR to set minWidth to 24.0. But it won't be enough to get the same available horizontal space for the input compared to before this PR.

The reason is that for InputDecoration there is 4.0 default gap between the input and the suffixIcon.
Previous version of the DropdownButtonFormField did not rely on InputDecoration.suffixIcon so it was not impacted by this gap.

I added an experimental commit to this PR to make it possible to remove this gap. This will not be the final solution, it is only a temporary commit to see if it helps with the Google testing failures.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@justinmc Are there many Google testing failures now?
The PR is in an experimental state (see my previous comment). The number and the kind of Google testing failures will determine how to proceed there. Thanks for having a look when you will get bandwidth (no hurry there).

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see any failures of the sort that I mentioned, where text no longer fits. In fact, I see some case where more text now fits than did before. However, the suffix is very close to the right edge now.

Sorry I missed this notification, feel free to ping me if I disappear again :)

@bleroux bleroux force-pushed the fix_dropdown_button_form_field_icon_not_vertically_centered branch 3 times, most recently from adaa282 to 5e67747 Compare March 24, 2025 15:06
@bleroux bleroux requested a review from justinmc April 7, 2025 07:22
@bleroux
Copy link
Contributor Author

bleroux commented Apr 18, 2025

Many thanks for the feedback 🙏 .
Based on #163205 (comment). I will mark this PR as draft, file a separate PR to make the inputDecoration prefix and suffix gaps configurable. And then come back to this PR. Especially trying to understand in which cases "the suffix is very close to the right edge now".

@bleroux bleroux marked this pull request as draft April 18, 2025 08:41
@flutter-dashboard
Copy link

This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@justinmc
Copy link
Contributor

Here's what I meant by the suffix icon being close to the right side:

The master branch Your screenshot of this PR in the description This PR currently
Screenshot 2025-04-18 at 11 23 33 AM 412859218-b5704453-66a3-4cb2-97ff-bef556bff377 Screenshot 2025-04-18 at 11 22 13 AM

You can see in the PR currently the suffix icon is further to the right than it was before you changed the PR.

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(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Center(
              child: SizedBox(
                width: 200,
                child: DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: InputDecoration(
                    fillColor: Colors.blueGrey.withOpacity(0.2),
                    filled: true,
                    labelText: 'Label text',
                  ),
                  items: [
                    DropdownMenuItem(
                      value: 'selected',
                      child: Text('Selected item'),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

@bleroux
Copy link
Contributor Author

bleroux commented Apr 18, 2025

Wow, thanks a lot for providing this sample and the screenshot.
For the moment, I'm surprised that the screenshot in my PR description did not match the result you got. I will try to find why there is such a discrepancy (maybe related to another InputDecoration parameter or maybe related to the platform used to run the sample). Anyway, thanks a lot for providing these very useful feedback 🙏

@bleroux bleroux force-pushed the fix_dropdown_button_form_field_icon_not_vertically_centered branch 2 times, most recently from 2126ae4 to 746ae5b Compare April 25, 2025 13:43
@bleroux
Copy link
Contributor Author

bleroux commented Apr 25, 2025

@justinmc I updated the PR based on your last comment and our discussion on #167558 (comment)

It turned out that the fix, in order to compute the correct suffixIconConstraints, should take into account if the input decoration is filled or outlined.

Because for a filled or outlined decoration the right padding is directly provided by the constraints added to the suffix icon, for instance constraints on mobile are 48x48 which means a left and right padding of 12.0. (FYI, on desktop it is be 8.0 because the suffixIconConstraints is 40x40, this is probably not intended as from the M3 spec, visual density usually applies only on the vertical direction, I will check that and file an issue if needed).

I updated the fix accordingly. Let me know how it goes with the Google tests.
FYI, I will need to add some more tests for verifying this fix.

And let me try to explain the layout:

Before the fix

DropdownButtonFormField was positioning the icon by setting the input decoration content to a Row containing both the selected item label and the icon (24x24).

For a filled or outlined decoration, the horizontal layout was: leftPadding (16.0) | selected item label | icon (24.0) | rightPadding (16.0).
(16.0 padding since very recently because it is due to #162157, before it was 12.0).

For a non-filled and non-outlined decoration, it was: leftPadding (0.0) | selected item label | icon (24.0) | rightPadding (0.0)

With the fix

DropdownButtonFormField is positioning the icon by setting the input decoration suffixIcon and suffixIconConstraints.

For a filled or outlined decoration, the horizontal layout is: leftPadding (16.0) | selected item label | suffixIconGap (4.0) | icon (24.0) | rightPadding (12.0).
Here the right padding is 12.0 and this is the compliant padding from the M3 spec: when there is no suffix icon right padding should be 16.0, when the is a suffixIcon it should be 12.0).
This means that, with the fix, the content's width is the same as before this fix. The difference is the icon moving by 4.0 pixel to the right (which will restore its position as before #162157).

For a non-filled and non-outlined decoration, it is: leftPadding (0.0) | selected item label | icon (24.0) | suffixIconGap (4.0) | rightPadding (0.0)
Here the difference will be the content width being reduced by 4.0 pixel and the icon should be at the same horizontal position.

Here is a combined screenshot to illustrate this. The top 3 fields showcase the fix, the bottom ones were captured without the fix:

image

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

void main() {
  runApp(const MyApp());
}

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

  final bool filled = true;
  static const List<DropdownMenuItem<String>> items = [
    DropdownMenuItem(value: 'selected', child: Text('Selected item')),
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: SizedBox(
            width: 200,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              spacing: 4.0,
              children: [
                DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: const InputDecoration(labelText: 'Raw'),
                  // Before https://github.com/flutter/flutter/pull/163205, width could be 176.
                  selectedItemBuilder:
                      (context) => [Container(height: 24, width: 172, color: Colors.amber)],
                  items: items,
                ),
                DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: const InputDecoration(labelText: 'Filled', filled: true),
                  selectedItemBuilder:
                      (context) => [Container(height: 24, width: 144, color: Colors.amber)],
                  items: items,
                ),
                DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: const InputDecoration(
                    labelText: 'Outlined',
                    border: OutlineInputBorder(),
                  ),
                  selectedItemBuilder:
                      (context) => [Container(height: 24, width: 144, color: Colors.amber)],
                  items: items,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

@bleroux bleroux force-pushed the fix_dropdown_button_form_field_icon_not_vertically_centered branch from 746ae5b to fa581cf Compare May 5, 2025 14:53
@bleroux bleroux marked this pull request as ready for review May 5, 2025 19:42
@bleroux bleroux force-pushed the fix_dropdown_button_form_field_icon_not_vertically_centered branch from fa581cf to 44fcdf4 Compare May 5, 2025 19:42
@bleroux bleroux force-pushed the fix_dropdown_button_form_field_icon_not_vertically_centered branch from 44fcdf4 to 25ff01a Compare May 6, 2025 18:40
@justinmc
Copy link
Contributor

justinmc commented May 6, 2025

Nice, I ran it locally and confirmed that the layout seems to be correct as you explained. The Google test check has disappeared though, let me try re-adding it.

Edit: Possibly an infrastructure problem (Google internal b/416058821) so I'm running the Google tests manually.

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.

I'm still seeing a horizontal change in the position of the suffix icon with this PR, I think that's not intentional because I don't see a horizontal change in the comparison image that you posted above in #163205 (comment), right? I think this is happening only in outlined inputs. Repro code below.

Otherwise all of the other Google test failures look expected (the arrow moved slightly vertically).

Before this PR After this PR
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(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Center(
              child: SizedBox(
                width: 200,
                child: DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Label text',
                  ),
                  items: [
                    DropdownMenuItem(
                      value: 'selected',
                      child: Text('Selected item'),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

@bleroux
Copy link
Contributor Author

bleroux commented May 12, 2025

@justinmc

I'm still seeing a horizontal change in the position of the suffix icon with this PR, I think that's not intentional because I don't see a horizontal change in the comparison image that you posted above in #163205 (comment), right?

This horizontal change is intentional. It is visible in the comparison image in #163205 (comment). But It would have been easier to see if I had put the after/before images closer 😅

#163205 (comment) was a very long comment, let me emphasize the section related to this horizontal change:

"
For a filled or outlined decoration
...
the content's width is the same as before. The difference is the icon moving by 4.0 pixels to the right (which will restore its position as before #162157).
"

@bleroux bleroux requested a review from justinmc May 12, 2025 15:19
@justinmc
Copy link
Contributor

Ah you're right, I can definitely see a change in the horizontal position for the outlined field in your screenshots, sorry about missing that. I'll re-review the Google failures and then autosubmit this.

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.

Renewing my LGTM 👍 . I reviewed all Google test failures and they are expected. There was some trouble with Frob but it's working now, this can be autosubmitted.

@justinmc justinmc added the autosubmit Merge PR when tree becomes green via auto submit App label May 12, 2025
@auto-submit auto-submit bot added this pull request to the merge queue May 12, 2025
Merged via the queue into flutter:master with commit 81de9ed May 12, 2025
75 of 76 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label May 12, 2025
@bleroux bleroux deleted the fix_dropdown_button_form_field_icon_not_vertically_centered branch May 13, 2025 04:44
auto-submit bot pushed a commit to flutter/packages that referenced this pull request May 13, 2025
flutter/flutter@54de32d...336a7ec

2025-05-13 [email protected] Add assert for index parameter in IndexedStack. (flutter/flutter#167757)
2025-05-13 [email protected] Fixed Android Lint Errors (flutter/flutter#168613)
2025-05-13 [email protected] Tab bar theme and dialog theme documentation cleanup (flutter/flutter#168724)
2025-05-13 [email protected] Roll Fuchsia Linux SDK from 6vjKe0bfYDVaECqBL... to 6J81agNhuK4q255Jj... (flutter/flutter#168712)
2025-05-12 [email protected] Make the barrier panel on the Material Drawer non-dismissible (flutter/flutter#164810)
2025-05-12 [email protected] Roll ICU from c9fb4b3a6fb5 to b929596baebf (5 revisions) (flutter/flutter#168691)
2025-05-12 [email protected] Fix DropdownButtonFormField icon not vertically centered (flutter/flutter#163205)
2025-05-12 [email protected] Android home/end keyboard shortcut support (flutter/flutter#168184)
2025-05-12 [email protected] Update `TESTOWNERS` for Android PV tests (flutter/flutter#168694)
2025-05-12 [email protected] Roll Dart SDK from 0bea6379f654 to 645d04a7a964 (14 revisions) (flutter/flutter#168679)
2025-05-12 [email protected] [Impeller] libImpeller: Allow setting text decorations. (flutter/flutter#168408)
2025-05-12 [email protected] Error when trying to use old HC mode when HCPP is enabled (flutter/flutter#168027)
2025-05-12 [email protected] Nav bar back label is not clipped mid-transition (flutter/flutter#168194)
2025-05-12 [email protected] Add test for stack trace mapping and test expression eval tests using DDC library bundle format (flutter/flutter#168017)
2025-05-12 [email protected] Remove CupertinoSliverNavigationBar background box when large title is extended (flutter/flutter#168407)
2025-05-12 [email protected] Label platform view modes using the unified naming scheme (flutter/flutter#168670)
2025-05-12 [email protected] Roll Packages from 7814fab to 6a28ad9 (2 revisions) (flutter/flutter#168669)
2025-05-12 [email protected] Update `Engine-artifacts.md` to reflect the new `engine.version` verifier (flutter/flutter#168413)
2025-05-12 [email protected] Roll Skia from 9f9e1f37917e to c97451da059f (1 revision) (flutter/flutter#168671)

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] 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
…r#9246)

flutter/flutter@54de32d...336a7ec

2025-05-13 [email protected] Add assert for index parameter in IndexedStack. (flutter/flutter#167757)
2025-05-13 [email protected] Fixed Android Lint Errors (flutter/flutter#168613)
2025-05-13 [email protected] Tab bar theme and dialog theme documentation cleanup (flutter/flutter#168724)
2025-05-13 [email protected] Roll Fuchsia Linux SDK from 6vjKe0bfYDVaECqBL... to 6J81agNhuK4q255Jj... (flutter/flutter#168712)
2025-05-12 [email protected] Make the barrier panel on the Material Drawer non-dismissible (flutter/flutter#164810)
2025-05-12 [email protected] Roll ICU from c9fb4b3a6fb5 to b929596baebf (5 revisions) (flutter/flutter#168691)
2025-05-12 [email protected] Fix DropdownButtonFormField icon not vertically centered (flutter/flutter#163205)
2025-05-12 [email protected] Android home/end keyboard shortcut support (flutter/flutter#168184)
2025-05-12 [email protected] Update `TESTOWNERS` for Android PV tests (flutter/flutter#168694)
2025-05-12 [email protected] Roll Dart SDK from 0bea6379f654 to 645d04a7a964 (14 revisions) (flutter/flutter#168679)
2025-05-12 [email protected] [Impeller] libImpeller: Allow setting text decorations. (flutter/flutter#168408)
2025-05-12 [email protected] Error when trying to use old HC mode when HCPP is enabled (flutter/flutter#168027)
2025-05-12 [email protected] Nav bar back label is not clipped mid-transition (flutter/flutter#168194)
2025-05-12 [email protected] Add test for stack trace mapping and test expression eval tests using DDC library bundle format (flutter/flutter#168017)
2025-05-12 [email protected] Remove CupertinoSliverNavigationBar background box when large title is extended (flutter/flutter#168407)
2025-05-12 [email protected] Label platform view modes using the unified naming scheme (flutter/flutter#168670)
2025-05-12 [email protected] Roll Packages from 7814fab to 6a28ad9 (2 revisions) (flutter/flutter#168669)
2025-05-12 [email protected] Update `Engine-artifacts.md` to reflect the new `engine.version` verifier (flutter/flutter#168413)
2025-05-12 [email protected] Roll Skia from 9f9e1f37917e to c97451da059f (1 revision) (flutter/flutter#168671)

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] 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
Ortes pushed a commit to Ortes/packages that referenced this pull request Jun 25, 2025
…r#9246)

flutter/flutter@54de32d...336a7ec

2025-05-13 [email protected] Add assert for index parameter in IndexedStack. (flutter/flutter#167757)
2025-05-13 [email protected] Fixed Android Lint Errors (flutter/flutter#168613)
2025-05-13 [email protected] Tab bar theme and dialog theme documentation cleanup (flutter/flutter#168724)
2025-05-13 [email protected] Roll Fuchsia Linux SDK from 6vjKe0bfYDVaECqBL... to 6J81agNhuK4q255Jj... (flutter/flutter#168712)
2025-05-12 [email protected] Make the barrier panel on the Material Drawer non-dismissible (flutter/flutter#164810)
2025-05-12 [email protected] Roll ICU from c9fb4b3a6fb5 to b929596baebf (5 revisions) (flutter/flutter#168691)
2025-05-12 [email protected] Fix DropdownButtonFormField icon not vertically centered (flutter/flutter#163205)
2025-05-12 [email protected] Android home/end keyboard shortcut support (flutter/flutter#168184)
2025-05-12 [email protected] Update `TESTOWNERS` for Android PV tests (flutter/flutter#168694)
2025-05-12 [email protected] Roll Dart SDK from 0bea6379f654 to 645d04a7a964 (14 revisions) (flutter/flutter#168679)
2025-05-12 [email protected] [Impeller] libImpeller: Allow setting text decorations. (flutter/flutter#168408)
2025-05-12 [email protected] Error when trying to use old HC mode when HCPP is enabled (flutter/flutter#168027)
2025-05-12 [email protected] Nav bar back label is not clipped mid-transition (flutter/flutter#168194)
2025-05-12 [email protected] Add test for stack trace mapping and test expression eval tests using DDC library bundle format (flutter/flutter#168017)
2025-05-12 [email protected] Remove CupertinoSliverNavigationBar background box when large title is extended (flutter/flutter#168407)
2025-05-12 [email protected] Label platform view modes using the unified naming scheme (flutter/flutter#168670)
2025-05-12 [email protected] Roll Packages from 7814fab to 6a28ad9 (2 revisions) (flutter/flutter#168669)
2025-05-12 [email protected] Update `Engine-artifacts.md` to reflect the new `engine.version` verifier (flutter/flutter#168413)
2025-05-12 [email protected] Roll Skia from 9f9e1f37917e to c97451da059f (1 revision) (flutter/flutter#168671)

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] 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.

DropdownButtonFormField arrow icon is misaligned vertically

2 participants