-
Notifications
You must be signed in to change notification settings - Fork 28.5k
Fix DropdownButtonFormField icon not vertically centered #163205
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Fix DropdownButtonFormField icon not vertically centered #163205
Conversation
3b28af6
to
955fb0b
Compare
There was a problem hiding this 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.
955fb0b
to
4d79b7a
Compare
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), |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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 :)
adaa282
to
5e67747
Compare
Many thanks for the feedback 🙏 . |
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 Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
Wow, thanks a lot for providing this sample and the screenshot. |
2126ae4
to
746ae5b
Compare
@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. And let me try to explain the layout: Before the fixDropdownButtonFormField 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). For a non-filled and non-outlined decoration, it was: leftPadding (0.0) | selected item label | icon (24.0) | rightPadding (0.0) With the fixDropdownButtonFormField 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). 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 is a combined screenshot to illustrate this. The top 3 fields showcase the fix, the bottom ones were captured without the fix: Code sample for the screenshotimport '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,
),
],
),
),
),
),
);
}
}
|
746ae5b
to
fa581cf
Compare
fa581cf
to
44fcdf4
Compare
44fcdf4
to
25ff01a
Compare
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. |
Description
This PR fixes
DropdownButtonFormField
suffix icon vertical alignment whenDropdownButtonFormField.inputDecoration
is provided without a hint text.Before:
The dropdown icon is misaligned vertically:
After:
The dropdown icon is aligned vertically:
Related Issue
Fixes DropdownButtonFormField arrow icon is misaligned vertically
Tests
Adds 1 test.