This is a specific example that requires case 2 and case 3 from this other post How to use the constraints and sizes of other widgets during the build phase
-------------------------BASIC HEIRARCHY-------------------------
main [FLEX] child 1: red (expanded) child 2: purple (non expanded, but it obeys its min constraint) [FLEX] ------child 1: green (non expanded, works as expected) ------child 2: yellow (I would like it to fill the rest of the space that purple has available but the system wont let me just use expanded)
-------------------------GOAL-------------------------
I want the yellow box to fill the rest of the space available inside the purple box.
NOTE: the very specific combination of widgets that don't allow me to wrap the yellow container in an expanded widget
-------------------------WHY I CANT USE EXPANDED-------------------------
If I wrap the yellow widget in an expanded it throws an error... here is why...
in that particular case I have 2 containers inside of a flex child 1(of main): the red one is expanding so... child 2(of main): the purple one tries to shrink wrap its children and take the least amount of space as possible but technically it has no max constraints (only min constraints which is why there is still some purple visible)
the purple child is also a flex and has 2 children, since the purple flex is trying to shrink wrap its children it will tell its children to do the same child 1(of purple): the green container does this and its fine because I want it to do this but... child 2(of purple): I want the yellow container to fill the space purple has created with its min-width param
problem is that the yellow containers purple parent is telling it to shrink wrap its children (as explained above) but then if I wrap it in an expanded widget you are telling the yellow container to expand or in other words not shrink wrap its children... and well the yellow container can both shrink wrap and not shrink wrap its children so you get an error
So... I need to know the calculated width of the purple container then the calculated width of the green container then the width of my yellow container would be yellow.width = purple.width - green.width
-------------------------CODE OUTPUT-------------------------
this shows the output of the code below
-------------------------MAIN.DART-------------------------
import 'package:flutter/material.dart';
import 'materialSheet.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
final appTitle = 'Material Sheets Demo';
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: ThemeData.dark(),
home: new MaterialSheet(
app: new Text("kill \n\n me plz"),
sheet: new Icon(Icons.keyboard),
attachment: new Icon(Icons.attachment),
position: sheetPosition.right,
placement: attachmentPlacement.inside,
sheetMin: 125.0,
),
);
}
}
-------------------------MATERIALSHEET.DART-------------------------
import 'package:flutter/material.dart';
//-------------------------Enumerations-------------------------
enum sheetPosition { top, right, bottom, left }
enum sheetType { modal, persistent }
enum attachmentPlacement { inside, outside }
class MaterialSheet extends StatelessWidget {
//-------------------------Parameters-------------------------
final Widget app;
final Widget sheet;
final Widget attachment;
final sheetPosition position;
final sheetType type; //TODO add in the scrim behind the thing
final attachmentPlacement placement;
final double sheetMin; //TODO
final double sheetMax; //TODO
final double percentBeforeOpen; //TODO
final bool autoOpenIndicator; //TODO
final double percentBeforeClose; //TODO
final bool autoCloseIndicator; //TODO
final bool vertiScroll; //TODO
final bool horiScroll; //TODO
final bool swipeToOpen; //TODO
final bool swipeToClose; //TODO
MaterialSheet(
{@required this.app,
@required this.sheet,
this.attachment,
this.position: sheetPosition.bottom,
this.type: sheetType.modal,
this.placement: attachmentPlacement.inside,
this.sheetMin,
this.sheetMax,
this.percentBeforeOpen: .5,
this.autoOpenIndicator: true,
this.percentBeforeClose: .5,
this.autoCloseIndicator: true,
this.vertiScroll: false,
this.horiScroll: false,
this.swipeToOpen: true,
this.swipeToClose: true});
//-------------------------Helper Code-------------------------k
BoxConstraints _calcBoxConstraints(bool fullWidth) {
if (sheetMin == null && sheetMax == null)
return new BoxConstraints();
else {
if (sheetMin != null && sheetMax != null) {
if (fullWidth) //we only care for height
return new BoxConstraints(
minHeight: sheetMin,
maxHeight: sheetMax,
);
else //we only care for width
return new BoxConstraints(minWidth: sheetMin, maxWidth: sheetMax);
} else {
if (sheetMin != null) {
//we only have min
if (fullWidth) //we only care for height
return new BoxConstraints(minHeight: sheetMin);
else //we only care for width
return new BoxConstraints(minWidth: sheetMin);
} else {
//we only have max
if (fullWidth) //we only care for h`eight
return new BoxConstraints(maxHeight: sheetMax);
else //we only care for width
return new BoxConstraints(maxWidth: sheetMax);
}
}
}
}
//-------------------------Actual Code-------------------------
@override
Widget build(BuildContext context) {
bool isWidthMax =
(position == sheetPosition.bottom || position == sheetPosition.top);
//-----Create the Widgets and Initially calculate Sizes
print("before test");
Scaffold testScaff = theSheet(isWidthMax, context);
print("after test");
//-----Apply Size constraints as needed
Align testAl = new Align();
return new Stack(
children: <Widget>[
//---------------Contains your Application
new Scaffold(
backgroundColor: Colors.green,
body: app,
),
//---------------Contains the Sheet
theSheet(isWidthMax, context),
],
);
}
Scaffold theSheet(bool isWidthMax, BuildContext context) {
Scaffold generatedScaffold = genScaff(isWidthMax);
EdgeInsetsGeometry padCheck = (((generatedScaffold.body as Flex).children[0] as Flexible).child as Container).padding;
print("value " + padCheck.toString());
return generatedScaffold;
}
Scaffold genScaff(bool isWidthMax) {
return new Scaffold(
body: new Flex(
direction: (isWidthMax) ? Axis.vertical : Axis.horizontal,
//ONLY relevant if position is top or bottom
textDirection: (position == sheetPosition.right)
? TextDirection.ltr
: TextDirection.rtl,
//ONLY relevant if position is left or right
verticalDirection: (position == sheetPosition.top)
? VerticalDirection.up
: VerticalDirection.down,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Flexible(
fit: FlexFit.loose,
child: new Container(
padding: EdgeInsets.all(18.3),
color: Colors.red,
)),
new ConstrainedBox(
constraints: _calcBoxConstraints(isWidthMax),
child: new Container(
color: Colors.purple,
child: new Flex(
direction: (isWidthMax) ? Axis.vertical : Axis.horizontal,
//ONLY relevant if position is top or bottom
textDirection: (position == sheetPosition.right)
? (placement == attachmentPlacement.inside)
? TextDirection.rtl
: TextDirection.ltr
: (placement == attachmentPlacement.inside)
? TextDirection.ltr
: TextDirection.rtl,
//ONLY relevant if position is left or right
verticalDirection: (position == sheetPosition.top)
? (placement == attachmentPlacement.inside)
? VerticalDirection.down
: VerticalDirection.up
: (placement == attachmentPlacement.inside)
? VerticalDirection.up
: VerticalDirection.down,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Container(
color: Colors.amberAccent,
child: sheet,
),
new Flexible(
fit: FlexFit.loose,
child: new Container(
color: Colors.greenAccent,
child: (attachment != null) ? attachment : null,
),
),
],
),
),
),
],
),
);
}
}
You need to wrap your inner Row
into a IntrinsicWidth
to enforce it to take the least amount of space possible based on it's content.
Thanks to that, you can now wrap a child of that inner row into an Expanded
without having exception.
new Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Expanded(
child: new Container(
color: Colors.red,
),
),
new ConstrainedBox(
constraints: new BoxConstraints(minWidth: 100.0),
child: new Container(
color: Colors.purple,
child: new IntrinsicWidth(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Container(
color: Colors.cyan,
child: new Icon(Icons.title),
),
new Expanded(
child: new Container(
color: Colors.yellow,
alignment: Alignment.center,
child: new Icon(Icons.theaters)),
),
],
),
),
),
),
],
),
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With