avoid_wrapping_in_padding
v0.4.0 Warning Fix Widget Replacement
Flags a Padding whose child already takes a padding argument of its own —
Container, ListView, GridView, SingleChildScrollView,
ReorderableListView, Chip, and any of your own widgets that expose one. The
wrapper is a whole extra render object doing what the child would have done for
free.
The check is structural, not a fixed list: the rule looks at the child’s
constructors and reports if any of them declares a named padding parameter.
Why use this rule
Section titled “Why use this rule”Each Padding in the tree is a RenderPadding to lay out and paint. When the
child already accepts padding:, moving the value inward removes a level of
nesting and a render object, and puts the inset next to the widget it belongs
to. The quick fix does the move, carrying the key across if the Padding had
one.
See also: Padding | ScrollView.padding
// ListView takes its own padding. Wrapping it insets the whole viewport, so// the scrollbar and the overscroll glow move inward with the content.Padding( padding: EdgeInsets.all(16), child: ListView(children: items),);// The inset now applies to the content; the viewport still fills the space.ListView(padding: EdgeInsets.all(16), children: items);Examples
Section titled “Examples”Your own widget counts too
Section titled “Your own widget counts too”Nothing here is hard-coded to Flutter’s widgets. Give a widget a padding
parameter and the rule starts reporting Padding around it:
class Panel extends StatelessWidget { const Panel({super.key, this.padding, required this.child});
final EdgeInsetsGeometry? padding; final Widget child;
@override Widget build(BuildContext context) => Container( color: const Color(0xFFEEEEEE), padding: padding, child: child, );}// Don't — Panel declares `padding`, so the wrapper is redundantPadding(padding: const EdgeInsets.all(8), child: Panel(child: body));
// DoPanel(padding: const EdgeInsets.all(8), child: body);Note that a padding parameter your widget then ignores will still make the
rule report — it reads the constructor signature, not what build does with the
value.
Wrapping a Container
Section titled “Wrapping a Container”Known limitations
Section titled “Known limitations”A child that already sets padding is left alone. Merging two insets is a
decision, not a rewrite:
// Not reportedPadding( padding: EdgeInsets.all(8), child: Container(padding: EdgeInsets.all(4), child: Text('Hello')),);A Padding with no child is never reported — there is nothing to move the
value into.
Only the immediate child is examined. Padding > Center > ListView is not
reported, even though the ListView could still take the inset, because moving
it across the Center would change the layout.
Configuration
Section titled “Configuration”This rule is in the opinionated preset, so it is on with
preset: opinionated, or by name:
rules: avoid_wrapping_in_padding: trueTo turn it off again:
rules: avoid_wrapping_in_padding: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”prefer_padding_over_container— Use Padding instead of Container when only padding or margin is set.avoid_border_all— Use Border.fromBorderSide instead of Border.all for const support.avoid_expanded_as_spacer— Use Spacer instead of Expanded with an empty child.avoid_incorrect_image_opacity— Use Image’s opacity parameter instead of wrapping in Opacity.