Reputation: 8012
Sometimes I want to arrange items in a column with different amounts of space between each item. A typical implementation uses SizedBox or Container.padding, but neither permits negative values. Are there any ways to achieve negative spacing as of Flutter 1.0?
return Column(
children: <Widget>[
Container(height:20, width: 20, color: Color(0x800000FF),),
SizedBox(height: -10,), // Illegal, can't be negative
Container(height:20, width: 20, color: Color(0x80FF0000),),
Container(
padding: EdgeInsets.fromLTRB(0, -10, 0, 0), // Illegal, can't be negative
child: Container(height:20, width: 20, color: Color(0x8000FF00),),
)
],
);
Upvotes: 2
Views: 3961
Reputation: 456
The best way using transform. Less code :-). If you want to increase position a Widget aka you want a "negative" margin, eg top (-10), you can do this: Transform.translate set the Offset(x, y)
Column(
children: [
Text("Fist Text in Column"),
Transform.translate(
offset: const Offset(0, -10),
child: Text("Second Text in Column")),
],
)
Have a nice day...
Upvotes: 7
Reputation: 6737
There is actually an article about a negative margin in flutter. I believed that the SO answer mentioned in the comments was also discussed there.
In CSS, margins have various meanings in the various layout models, most commonly, they are one of several values that contribute to computing the offset that the block layout model uses to place subsequent children; a negative total margin in this case merely means the next child is placed above the bottom of the previous child instead of after it.
In Flutter, as in CSS, there are several layout models; however, there is currently no widget that is equivalent to the CSS block layout model (which supports margin collapsing, negative margins, skipping floats, etc).
Such a layout model could certainly be implemented, it just hasn’t been implemented yet, at least not in the framework itself.
To implement such a layout model, you would create a RenderBox descendant similar to RenderFlex or RenderListBody, probably providing a way to set the margins of each child using a ParentDataWidget in the same way that Flex children can have their flex configured using the Expanded widget.
Probably the most complicated part of designing a new layout model like this would be deciding how to handle overflow or underflow when the children are too big or too small to fit the constraints passed to this new layout render an object.
The RenderFlex render object has a way to distribute the space if the children underflow, and considers it an error if they overflow (in debug mode, this is shown by a yellow-and-black striped warning area and a message logged to the console); the RenderListBody render the object.
On the other hand, takes the view that the constraints must be unbounded in the main axis, which means you can basically only use this layout model inside a list (hence the name).
If writing a new layout model is not attractive, you could use one of the existing layout widgets that allow overlapping children. A stack is an obvious choice, where you set the explicit positions of each child and they can overlap arbitrarily this is vaguely similar to the CSS absolute position layout model. Another option is the CustomMultiChildLayout widget, which lets you layout and position each child in turn.
With this, you could position each child one after the other, simulating negative margins by setting the position of the subsequent child to a value that’s derived from the size and position of the previous child, but such that the subsequent child’s top is above the previous child’s bottom.
Flutter has a sophisticated but effective algorithm for rendering its widgets. Margins and Paddings are analyzed at runtime, and the final size and position of the widget are determined.
when you try to issue a negative margin you are purposefully creating a not valid layout where a widget is somehow dropping out of the space it is supposed to occupy.
Concluded that it is not ideal but there are some workarounds if really needed:
No, Flutter does not allow negative margins but just in case you still want your widgets to overlap each other…
you can use a Stack with Positioned which will allow you to generate the layout which you can do with negative margins.
Upvotes: 0