Reputation: 475
I have a Row that has 2 children like this:
----------------------
| wide child1 | child2 |
----------------------
Is there any way to make each cell be equal in size, so that each cell's width would be equal to the width of the widest cell? Like this:
--------------------------
| wide child1 | child2 |
--------------------------
So the whole Row would take biggestCellWidth * numOfChildren
in width.
I couldn't achieve this behavior with built-in widgets and tried to implement MultiChildLayoutDelegate
but it also doesn't work since I can't measure children.
Upd:
// in build function
Container(
height: 48,
child: Material(
clipBehavior: Clip.antiAlias,
borderRadius: BorderRadius.circular(16),
color: Theme.of(context).colorScheme.primary,
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
// this widgets should be equal in width
_buildButton(
text: "Review",
onTap: _onReviewTap,
),
_buildButton(
text: "Buy",
onTap: _onBuyTap,
),
],
),
),
);
Widget _buildButton({
@required String text,
@required Function onTap,
@required EdgeInsets padding,
}) {
return InkWell(
onTap: onTap,
child: Center(
child: Text(
text,
style: TextStyle(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
);
}
Upvotes: 5
Views: 10270
Reputation: 84
Use Expanded with the same flex value to divide the space equally along the main axis. Here you have to understand what is the gist of the main axis. I suggest carefully reading this link: https://api.flutter.dev/flutter/widgets/Column-class.html
For the 'Column' widget, the main axis is vertical-y, while the 'Row' widget has a horizontal-x axis as its main axis. You can check the below code to understand how Expanded is used.
Use DartPad (https://dartpad.dev/?id) to try more example and get to know how Expanded works.
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
color: Colors.amber,
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.red,
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.green,
),
),
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
),
),
],
);
}
}
Upvotes: 3
Reputation: 7149
I think what you want is a Table? For example:
Table(
columnWidths: const {
0: FlexColumnWidth(),
1: FlexColumnWidth(),
},
children: [
TableRow(
children: [
Text(
"Review",
),
Text(
"Buy",
),
]
),
],
)
Upvotes: 8
Reputation: 9873
You mentioned that all your children are Text
widget. We can render texts to learn their size (reference), choose maximum width and do layout with MultiChildLayoutDelegate
. It's a bit hacky, but will work:
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
final texts = [
Text('loooooooooooong text'),
Text('short one'),
Text('one more'),
];
final children = <Widget>[
for (int i = 0; i < texts.length; i++)
LayoutId(
id: '$_kLayoutKey$i',
child: Container(
color: Color.fromARGB(255, Random().nextInt(255), Random().nextInt(255), Random().nextInt(255)),
child: texts[i],
),
),
];
return Scaffold(
appBar: AppBar(),
body: SafeArea(
child: CustomMultiChildLayout(
delegate: _CircularLayoutDelegate(texts, 14),
children: children,
)
),
);
}
}
const String _kLayoutKey = 'test';
class _CircularLayoutDelegate extends MultiChildLayoutDelegate {
_CircularLayoutDelegate(this.texts, this.fontSize);
final double fontSize;
final List<Text> texts;
double _calcTextWidth(BoxConstraints constraints, Text textWidget) {
RenderParagraph renderParagraph = RenderParagraph(
TextSpan(
text: textWidget.data,
style: TextStyle(
fontSize: fontSize,
),
),
textDirection: TextDirection.ltr,
maxLines: 1,
);
renderParagraph.layout(constraints);
return renderParagraph.getMinIntrinsicWidth(fontSize).ceilToDouble();
}
@override
void performLayout(Size size) {
final textSizes = [
for (final text in texts)
_calcTextWidth(BoxConstraints.loose(size), text),
];
final maxWidth = textSizes.fold<double>(0, (p, v) {
final textWidth = v;
return textWidth > p ? textWidth : p;
});
final textConstraint = BoxConstraints(
maxWidth: maxWidth,
minWidth: maxWidth,
maxHeight: size.height,
);
for (int i = 0; i < texts.length; i++) {
final String childId = '$_kLayoutKey$i';
if (hasChild(childId)) {
layoutChild('$_kLayoutKey$i', textConstraint);
positionChild(
childId,
Offset(maxWidth * i, 0),
);
}}
}
@override
bool shouldRelayout(_CircularLayoutDelegate oldDelegate) => oldDelegate.texts != texts;
}
Upvotes: 2
Reputation: 2448
You can wrap each widget inside Flexible with the same flex number
Upvotes: -1
Reputation: 7990
Wrap your child1 and child2 inside Expanded,
Row(
children: <Widget>[
Expanded(
child: Container(
color: Colors.amber,
height: 100,
),
),
Expanded(
child: Container(
color: Colors.amber,
height: 100,
),
),
Upvotes: 13