Skip to content
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

When setting up InputDecoration contentPadding, you must set isDense or it won't work #196

Open
laterdayi opened this issue Oct 13, 2023 · 3 comments
Assignees
Labels
documentation Improvements or additions to documentation question This issue is a usage question and will be moved to the Discussions section. works as expected Reported issue is not a bug, everything works as expected and designed

Comments

@laterdayi
Copy link

super(
          decoration: decoration != null
              ? decoration.copyWith(contentPadding: _contentPadding(size), )
              : InputDecoration(contentPadding: _contentPadding(size),),
        );

  static EdgeInsetsGeometry? _contentPadding(CustomTextFormFieldSize size) {
    switch (size) {
      case CustomTextFormFieldSize.small:
        return const EdgeInsets.symmetric(horizontal: 12, vertical: 6);
      case CustomTextFormFieldSize.middle:
        return const EdgeInsets.symmetric(horizontal: 12, vertical: 12);
      case CustomTextFormFieldSize.large:
        return const EdgeInsets.symmetric(horizontal: 12, vertical: 20);
    }
  }

When set to CustomTextFormFieldSize. Small, contentPadding cannot change, you must specify isDense will only take effect, when CustomTextFormFieldSize. Large when it is normal

@rydmike
Copy link
Owner

rydmike commented Oct 14, 2023

Hi @laterdayi,

Interesting find 👍🏻 Yes indeed if I make a larger padding, like this:

final ThemeData lightTheme = FlexThemeData.light(
  scheme: FlexScheme.indigoM3,
  subThemesData: const FlexSubThemesData(
    useM2StyleDividerInM3: true,
    inputDecoratorRadius: 12.0,
    popupMenuRadius: 10.0,
    menuRadius: 12.0,
    menuPadding: EdgeInsetsDirectional.fromSTEB(10, 20, 10, 16),
    menuIndicatorRadius: 8.0,
  ),
  keyColors: const FlexKeyColors(),
  tones: FlexTones.chroma(Brightness.light),
  useMaterial3: true,
);

and this

final InputDecorationTheme inputDecorationThemeLight =
    lightTheme.inputDecorationTheme.copyWith(
  isDense: false,
  contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 30),
);

and in MaterialApp set light theme to:

      theme: lightTheme.copyWith(
        inputDecorationTheme: inputDecorationThemeLight,
      ),

Screenshot 2023-10-14 at 23 53 26

Then if I use:

final InputDecorationTheme inputDecorationThemeLight =
    lightTheme.inputDecorationTheme.copyWith(
  isDense: true,
  contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 30),
);

or

final InputDecorationTheme inputDecorationThemeLight =
    lightTheme.inputDecorationTheme.copyWith(
  contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 30),
);

The result is identical.


However, you are right if I use:

final InputDecorationTheme inputDecorationThemeLight =
    lightTheme.inputDecorationTheme.copyWith(
  isDense: true,
  contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
);

I get this:

Screenshot 2023-10-14 at 23 57 53

But if I use:

final InputDecorationTheme inputDecorationThemeLight =
    lightTheme.inputDecorationTheme.copyWith(
  isDense: false,
  contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
);

or

final InputDecorationTheme inputDecorationThemeLight =
    lightTheme.inputDecorationTheme.copyWith(
  contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
);

The result is this:

Screenshot 2023-10-15 at 00 04 21

It appears the contentPadding will grow but not shrink beyond a certain limit, if isDense is not set to true.

Let's check the docs:

  /// Whether the input decorator's child is part of a dense form (i.e., uses
  /// less vertical space).
  ///
  /// Defaults to false.
  final bool isDense;

  /// The padding for the input decoration's container.
  ///
  /// The decoration's container is the area which is filled if
  /// [InputDecoration.filled] is true and bordered per the [border].
  /// It's the area adjacent to [InputDecoration.icon] and above the
  /// [InputDecoration.icon] and above the widgets that contain
  /// [InputDecoration.helperText], [InputDecoration.errorText], and
  /// [InputDecoration.counterText].
  ///
  /// By default the [contentPadding] reflects [isDense] and the type of the
  /// [border]. If [isCollapsed] is true then [contentPadding] is
  /// [EdgeInsets.zero].
  final EdgeInsetsGeometry? contentPadding;

No clue there why this is so. Let's check the relevant Flutter code:

    // The _Decoration widget and _RenderDecoration assume that contentPadding
    // has been resolved to EdgeInsets.
    final TextDirection textDirection = Directionality.of(context);
    final EdgeInsets? decorationContentPadding = decoration.contentPadding?.resolve(textDirection);

    final EdgeInsets contentPadding;
    final double floatingLabelHeight;
    if (decoration.isCollapsed) {
      floatingLabelHeight = 0.0;
      contentPadding = decorationContentPadding ?? EdgeInsets.zero;
    } else if (!border.isOutline) {
      // 4.0: the vertical gap between the inline elements and the floating label.
      floatingLabelHeight = (4.0 + 0.75 * labelStyle.fontSize!) * MediaQuery.textScaleFactorOf(context);
      if (decoration.filled ?? false) {
        contentPadding = decorationContentPadding ?? (decorationIsDense
          ? const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0)
          : const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0));
      } else {
        // Not left or right padding for underline borders that aren't filled
        // is a small concession to backwards compatibility. This eliminates
        // the most noticeable layout change introduced by #13734.
        contentPadding = decorationContentPadding ?? (decorationIsDense
          ? const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0)
          : const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 12.0));
      }
    } else {
      floatingLabelHeight = 0.0;
      contentPadding = decorationContentPadding ?? (decorationIsDense
        ? const EdgeInsets.fromLTRB(12.0, 20.0, 12.0, 12.0)
        : const EdgeInsets.fromLTRB(12.0, 24.0, 12.0, 16.0));
    }

Gotta say it looks like it with the outline border, it should be hitting that last else, that is what I originally thought and thus we should get whatever content padding value is defined as padding, regardless of the isDense setting, BUT we do not, it does not shrink as much as it is set to.


However, if you do something like this:

final InputDecorationTheme inputDecorationThemeLight =
    lightTheme.inputDecorationTheme.copyWith(
  isDense: false,
  constraints: BoxConstraints.tight(const Size(double.infinity, 20)),
  contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0),
);

The isDense won't matter, and you get this:

Screenshot 2023-10-15 at 00 33 10

You can make it super slim, so slim it becomes useless. With content padding only you cannot do that, so you cannot shoot yourself in the foot with it.


Of course none of these things are related to FlexColorScheme, this is just vanilla Flutter SDK behavior with these properties, but certainly an interesting find. From FCS point of view, it does whatever the props in Flutter do, even if they area bit odd 😄

Later I might dig into why it actually behaves like this by debugging it further. It could be some default min constraints, but at quick glance I did not find where it would set that to be tighter when using isDense true, but it might be in there somewhere, or it might be something else.


EDIT:

I will add this find to the property docs in FlexColorScheme for version 7.4.0 though, as it is useful info that the Flutter docs do not mention anywhere.

@rydmike rydmike self-assigned this Oct 14, 2023
@rydmike rydmike added works as expected Reported issue is not a bug, everything works as expected and designed documentation Improvements or additions to documentation question This issue is a usage question and will be moved to the Discussions section. labels Oct 14, 2023
@laterdayi
Copy link
Author

I am also confused about this part, it is not clear why flutter is designed this way, if only set the constraints: BoxConstraints.tight(const Size(double-infinity, 60)) without setting the contentPadding then the input box will be very small and the cursor will be very short

@rydmike
Copy link
Owner

rydmike commented Oct 16, 2023

While this is technically not a FlexColorScheme issue, I'm keeping this issue open to remind myself to dig a bit deeper into why this works the way it does. Maybe it is as intended in Flutter too, maybe not. If not, I might open an issue about it in Flutter SDK. I already updated the doc for the properties in FCS docs for next version a bit.

Good find! 👍🏻 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation question This issue is a usage question and will be moved to the Discussions section. works as expected Reported issue is not a bug, everything works as expected and designed
Projects
None yet
Development

No branches or pull requests

2 participants