J'ai une rangée qui a 2 enfants comme ceci:
// 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, ), ), ), ); }
Existe-t-il un moyen de rendre chaque cellule égale en taille, de sorte que la largeur de chaque cellule soit égale à la largeur de la cellule la plus large? Comme ça:
-------------------------- | wide child1 | child2 | --------------------------
Ainsi, toute la ligne prendrait biggestCellWidth * numOfChildren
de largeur de biggestCellWidth * numOfChildren
en largeur.
Je n'ai pas pu obtenir ce comportement avec des widgets MultiChildLayoutDelegate
et MultiChildLayoutDelegate
essayé d'implémenter MultiChildLayoutDelegate
mais cela ne fonctionne pas non plus car je ne peux pas mesurer les enfants.
Actualiser:
---------------------- | wide child1 | child2 | ----------------------
4 Réponses :
Enveloppez votre enfant1 et votre enfant2 dans Expanded ,
Row( children: <Widget>[ Expanded( child: Container( color: Colors.amber, height: 100, ), ), Expanded( child: Container( color: Colors.amber, height: 100, ), ),
Cela ne fonctionne pas si je ne spécifie pas explicitement la largeur de Row. Je ne veux pas faire cela, car tous les enfants sont des widgets de Text
qui peuvent avoir une largeur différente selon la langue.
Ou si vous souhaitez utiliser Flexible
au lieu de Expanded
, n'oubliez pas d'utiliser fit:FlexFit.tight
. pour donner la même taille aux deux enfants.
@frozzyk partagez votre morceau de morue
Vous pouvez envelopper chaque widget dans Flexible avec le même numéro de flex
Cela ne fonctionne pas dans mon cas, car la Row
parent n'a pas de taille fixe.
Vous avez mentionné que tous vos enfants sont des widgets de Text
. Nous pouvons rendre les textes pour connaître leur taille ( référence ), choisir la largeur maximale et faire la mise en page avec MultiChildLayoutDelegate
. C'est un peu piraté, mais cela fonctionnera:
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; }
On dirait ce que je veux, merci! Dommage que ce soit si difficile à faire en flottement.
Que faire si les widgets ne sont pas du texte?
@frozzyk Je suppose que vous devez aller encore plus bas et travailler avec des objets de rendu (par exemple, comme la classe Flex
qui s'étend de MultiChildRenderObjectWidget), et ce sera plus difficile. Vous pouvez accéder aux boîtes de performLayout
enfants dans la méthode performLayout
et connaître leur taille.
Je pense que ce que tu veux, c'est une table ? Par exemple:
Table( columnWidths: const { 0: FlexColumnWidth(), 1: FlexColumnWidth(), }, children: [ TableRow( children: [ Text( "Review", ), Text( "Buy", ), ] ), ], )
On dirait ce dont j'ai besoin. Je vais essayer ça plus tard. Merci
Voulez-vous mettre en page des widgets de texte comme ça?