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

use_decorated_box seems to be wrong: Its fix is not equivalent and changes UI #3286

Open
fzyzcjy opened this issue Mar 14, 2022 · 6 comments
Labels
false-positive P3 A lower priority bug or feature request set-none Does not affect any rules in a defined rule set (e.g., core, recommended, flutter) type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@fzyzcjy
Copy link

fzyzcjy commented Mar 14, 2022

Hi thanks for the linter! I use linter a lot, and when the use_decorated_box suggests me to replace Container with DecoratedBox I did that. Later I realized it has bugs.

A very simple reproducible sample is like:

Container(
  decoration: BoxDecoration(
    border: Border.all(width: 1),
  ),
  child: MyChildWidget(),
)

With its auto-fixed DecoratedBox version:

DecoratedBox(
  decoration: BoxDecoration(
    border: Border.all(width: 1),
  ),
  child: MyChildWidget(),
)

Suppose originally the page is 100x100 pixel. Then, the MyChildWidget in Container version will be 99x99, while that in DecoratedBox version will be 100x100 - no padding is automatically added to avoid the children to collide with the decoration! This caused some of my UI to have subtle bugs later on.

By the way, we can confirm this when looking at source code of Container:

  EdgeInsetsGeometry? get _paddingIncludingDecoration {
    if (decoration == null || decoration!.padding == null)
      return padding;
    final EdgeInsetsGeometry? decorationPadding = decoration!.padding;
    if (padding == null)
      return decorationPadding;
    return padding!.add(decorationPadding!);
  }

Widget build() {
...
    final EdgeInsetsGeometry? effectivePadding = _paddingIncludingDecoration;
    if (effectivePadding != null)
      current = Padding(padding: effectivePadding, child: current);

    if (decoration != null)
      current = DecoratedBox(decoration: decoration!, child: current);
...
}

So, if Container.decoration exists, it will automatically extra pad itself.

@pq
Copy link
Member

pq commented Mar 14, 2022

/fyi @minhqdao

@minhqdao
Copy link
Contributor

You're right, the Container is designed to be convenience widget that does some extra things internally. In this case, it adds padding to its child to account for the size of the Decoration. To achieve the same with a DecoratedBox, you'd need to wrap its child with a Padding:

final decoration = BoxDecoration(border: Border.all(width: 2));

DecoratedBox(
  decoration: decoration,
  child: Padding(
    padding: decoration.padding!,
    child: const MyChild(),
  ),
)

Nevertheless, this means that a DecoratedBox is not an exact replacement for a Container when only decoration was provided. Not quite sure what we should do with the linting rule then. 🤔

@fzyzcjy
Copy link
Author

fzyzcjy commented Mar 16, 2022

@minhqdao Thanks for the reply.

Not quite sure what we should do with the linting rule then. 🤔

Well, maybe deprecate this lint? I really did not expect an official lint with seemingly trivial fix will lead to such behavior

@srawlins srawlins added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label Jun 30, 2022
@bwilkerson bwilkerson added P3 A lower priority bug or feature request set-none Does not affect any rules in a defined rule set (e.g., core, recommended, flutter) labels Nov 7, 2022
@PawlikMichal25
Copy link

Related: #3344

@srawlins
Copy link
Member

CC @goderbauer

Is this still a sound lint rule? should we just make the quick-fix better?

@goderbauer
Copy link
Contributor

In its current form, the lint rule is not great and we've refrained from using it in the framework:

https://github.com/flutter/flutter/blob/980b5a1976883ea99301b6c6205204841ff565e8/analysis_options.yaml#L237

IMO, the rule itself doesn't provide a ton of value and contains this subtile padding foot gun. So I'd be in favor of just deprecating it. If we really want to salvage it, we'd have to improve its documentation around the padding issue (and also update its quick-fix to take that into consideration).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
false-positive P3 A lower priority bug or feature request set-none Does not affect any rules in a defined rule set (e.g., core, recommended, flutter) type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

7 participants