Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add InputDecoration.suffixIconGap #167558

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

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bleroux
Copy link
Contributor

@bleroux bleroux commented Apr 22, 2025

Description

This PR introduces InputDecoration.suffixIconGap and InputDecoration.suffixIconGap.
Those parameters make it possible to configure the gap between the input decoration content and the suffix icon (defaults are 4 pixels for M3 and 0 for M2). This gap was already implemented in InputDecoration but not configurable.

Related Issue

Needed to make progress on #163205.

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 Apr 22, 2025
@bleroux bleroux force-pushed the add_InputDecoration.suffixIconGap branch from 69cf830 to bd8f87c Compare April 22, 2025 15:02
@bleroux bleroux requested a review from justinmc April 22, 2025 16:18
@bleroux
Copy link
Contributor Author

bleroux commented Apr 22, 2025

@justinmc
Configuring the gap between the content and the suffix icon would help to make progress on #163205.
#163205 is a proposed fix for #157074. The solution is to rely on InputDecorator to fix the suffix icon vertical positioning. But because there is a default 4 pixels gap between the content and the icon, it is not possible to comply to the current DropdownButtonFormField positioning.
Being able to configure this gap will solve this problem.

I did not consider a similar parameter for the prefix in this PR.

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.

Can you explain why DropdownButtonFormField would need to use this to match the Material spec but TextField would not? E.g. why this needs to be a public API.

I thought that I had seen one or more issues that mentioned wanting control over this kinds of gap spacing, but I couldn't find any with a quick search. My opinion is that it's probably useful to let people control this gap spacing, but there will be a maintenance burden and InputDecorator's _layout method is already super complex, so we should be sure that the upsides are worth the downsides.

I am ok with leaving out prefixIconGap for now.

@bleroux
Copy link
Contributor Author

bleroux commented Apr 22, 2025

@justinmc

Can you explain why DropdownButtonFormField would need to use this to match the Material spec but TextField would not?

DropdownMenuFormField is currently using a Row to position the selected item label and the arrow down/up icon. Doing so there is no gap between the label and the icon (this is the root cause of the issue described in #157074).
Another way to explain it: DropdownButtonFormField uses an InputDecorator but instead of relying on InputDecoration.suffixIcon, it puts the selected item label and the icon into a Row and set that Row as the InputDecorator content.

#163205 removes the icon from the Row and passes it to InputDecorator.suffixIcon. This fixes the vertical alignment issue as it leverages the existing InputDecoration positioning logic.

E.g. why this needs to be a public API.

The fix in #163205 relies on configuring the InputDecorator used by DropdownButtonFormField. I don't think this can be done without making this parameter public.

In summary, the question is does fixing #157074 is worth adding a new parameter to InputDecoration which is already complex (and if we add this parameter for the suffix icon, someone will probably ask for something similar for the prefix icon).
I don't have a strong opinion on this. Maybe there is another way to fix #157074 (but I don't see one for the moment).

@bleroux bleroux force-pushed the add_InputDecoration.suffixIconGap branch from bd8f87c to df29661 Compare April 23, 2025 07:05
@bleroux bleroux force-pushed the add_InputDecoration.suffixIconGap branch from df29661 to 02ada41 Compare April 24, 2025 06:34
@bleroux bleroux requested a review from justinmc April 24, 2025 19:22
@justinmc
Copy link
Contributor

I think this is worth fixing even if we have to add the suffixGap parameter, but I want to make sure there's not a better way.

I notice that the horizontal position of the suffix of DropdownButtonFormField (top) is off compared to TextField (middle) and raw InputDecorator (bottom). Is that something that could/should be fixed to avoid needing suffixGap?

(This screenshot is from master so the vertical position is still off, but ignore that.)

Screenshot from 2025-04-24 14-49-01

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: Center(
          child: SizedBox(
            width: 200,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: InputDecoration(
                    labelText: 'Label text',
                  ),
                  padding: EdgeInsets.only(right: 34.0),
                  items: [
                    DropdownMenuItem(
                      value: 'selected',
                      child: Text('Selected item'),
                    ),
                  ],
                ),
                InputDecorator(
                  decoration: InputDecoration(
                    labelText: 'Label text',
                    suffixIcon: Icon(Icons.arrow_drop_down),
                  ),
                ),
                TextField(
                  decoration: InputDecoration(
                    labelText: 'Label text',
                    suffixIcon: Icon(Icons.arrow_drop_down),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

@bleroux
Copy link
Contributor Author

bleroux commented Apr 25, 2025

Yes, the suffix icon horizontal position is also different in DropdownButtonFormField.
From your code sample and screenshot there is an explicit padding set for the DropdownButtonFormField (probably a leftover after some experimentation). Here is the screenshot if I remove it:

image

Code sample without the 34 right padding
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: Center(
          child: SizedBox(
            width: 200,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: InputDecoration(labelText: 'Label text'),
                  //padding: EdgeInsets.only(right: 34.0),
                  items: [DropdownMenuItem(value: 'selected', child: Text('Selected item'))],
                ),
                InputDecorator(
                  decoration: InputDecoration(
                    labelText: 'Label text',
                    suffixIcon: Icon(Icons.arrow_drop_down),
                  ),
                ),
                TextField(
                  decoration: InputDecoration(
                    labelText: 'Label text',
                    suffixIcon: Icon(Icons.arrow_drop_down),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

The reason why the horizontal position is not the same is that DropdownButtonFormField put the suffix in a Row after the content and does not add any padding or constraints to the icon. So the icon is 24x24 and the content expands on all the remaining width.

image

With a default InputDecorator, the suffixIcon constraints are set to 48x48 (default tap target size on mobile) or 40x40 (default target size on desktop). There is also this 4 pixels gap before the suffixIcon:

image

Code sample updated to make InputDecorator content visible
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: Center(
          child: SizedBox(
            width: 200,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                DropdownButtonFormField<String>(
                  onChanged: (_) {},
                  decoration: InputDecoration(labelText: 'Label text'),
                  //padding: EdgeInsets.only(right: 34.0),
                  items: [DropdownMenuItem(value: 'selected', child: Text('Selected item'))],
                ),
                InputDecorator(
                  decoration: InputDecoration(
                    labelText: 'Label text',
                    suffixIcon: Icon(Icons.arrow_drop_down),
                  ),
                  child: Container(height: 24, color: Colors.amber),
                ),
                TextField(
                  decoration: InputDecoration(
                    labelText: 'Label text',
                    suffixIcon: Icon(Icons.arrow_drop_down),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

#163205 fix will mimics existing DroddownButtonFormField horizontal positioning by setting InputDecoration.suffixIconConstraints to 24. Without the ability to remove the 4 pixels gap there will be a small difference which results in the content width losing 4 pixels. Based on #163205 (comment), it seems to break several Google tests. But maybe the breakages where related to some width missing for another reason. Let me update #163205 as it currently contains experimentation and part of the fix was missing. That way you will be able to see what are the remaining Google testing failures and see if removing the gap is really needed.

@bleroux
Copy link
Contributor Author

bleroux commented May 6, 2025

Marking as WIP as it might not be needed, see #163205 (comment).
I will close it, once #163205 is merged.

@bleroux bleroux marked this pull request as draft May 6, 2025 20:12
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.

2 participants