How to achieve expansion of a widget in both vertical (height) and horizontal (width) direction - flutter

The code below lays out a chart in which I'd need to achieve for the chart to be expanded in both vertical (height) and horizontal (width) direction. The suggested method (e.g. https://docs.flutter.io/flutter/widgets/Row-class.html) is to use Expanded in Row or Column.
The chart widget I am trying to expand extends CustomPaint, with no children, everything is painted using a CustomPainter on canvas, in the CustomPainter.paint(canvas, size).
This code
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'vvvvvvvv:',
),
new RaisedButton(
color: Colors.green,
onPressed: _chartStateChanger,
),
new Text(
'vvvvvvvv:',
),
new Expanded( // Expanded in Column, no expansion vertically
child: new Row(
children: [
new Text('>>>'),
new Expanded(// Expanded in Row, expands horizontally
child: new Chart( // extends CustomPaint
// size: chartLogicalSize,
painter: new ChartPainter( // extends CustomPainter
chartData: _chartData,
chartOptions: _chartOptions,
),
),
),
new Text('<<<'),
],
), // row
),
new Text('^^^^^^:'),
new RaisedButton(
color: Colors.green,
onPressed: _chartStateChanger,
),
],
),
),
);
result looks like this: (code of ChartPainter is not shown for brevity)
Inside the ChartPainter.paint(canvas, size) there is a print() printing the size.
print(" ### Size: paint(): passed size = ${size}");
The result from the paint->print above is:
I/flutter ( 4187): ### Size: paint(): passed size = Size(340.0, 0.0)
The print along with the image shows, that the width expansion on the row level was passed to the CustomPainter.print(canvas, size) (width = 340.0), but the height expansion on the column did not get passed to the custom painter print (height = 0.0). Although the result shows that the row did get it's expanded height, if was not passed inside the row to the CustomPainter - 0 height was received.
What do I need to change to achieve the height expansion as well?
Thanks

Here is a reduced test case for the issue you are seeing. The solution is to give your Row a crossAxisAlignment of CrossAxisAlignment.stretch. Otherwise it will try to determine the intrinsic height of your CustomPaint which is zero because it doesn't have a child.
import 'package:flutter/material.dart';
// from https://stackoverflow.com/questions/45875334/how-to-achieve-expansion-of-a-widget-in-both-vertical-height-and-horizontal-w
class MyCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
// NOT using crossAxisAlignment: CrossAxisAlignment.stretch => width = 222.0, height=0.0
// using crossAxisAlignment: CrossAxisAlignment.stretch => width = 222.0, height=560.0
print("width = ${size.width}, height=${size.height}");
canvas.drawRect(Offset.zero & size, new Paint()..color = Colors.blue);
}
#override
bool shouldRepaint(MyCustomPainter other) => false;
}
void main() {
runApp(new MaterialApp(
home: new Scaffold(
body: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text('Above Paint'),
// Expanded - because we are in Column, expand the
// contained row's height
new Expanded(
child: new Row(
// The crossAxisAlignment is needed to give content height > 0
// - we are in a Row, so crossAxis is Column, so this enforces
// to "stretch height".
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new Text('Left of Paint'),
// Expanded - because we are in Row, expand the
// contained Painter's width
new Expanded(
child: new CustomPaint(
painter: new MyCustomPainter(),
),
),
new Text('Right of Paint'),
],
),
),
new Text('Below Paint'),
],
)
),
));
}

There is a better way than nesting Row, Expanded and Column widget. You can use the Container widget with Constraints to BoxConstraints.expand().
Example Code:
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints.expand(),
child: FutureBuilder(
future: loadImage(),
builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
switch(snapshot.connectionState) {
case ConnectionState.waiting :
return Center(child: Text("loading..."),);
default:
if (snapshot.hasError) {
return Center(child: Text("error: ${snapshot.error}"),);
} else {
return ImagePainter(image: snapshot.data);
}
}
},
),
);
}

Use SizedBox.expand:
SizedBox.expand(
child: YourWidget() // Could be anything like `Column`, `Stack`...
)

For those who struggled to get gradient together with Material behaviour:
return new Stack(
children: <Widget>[
new Material(
elevation: 10,
borderRadius: new BorderRadius.all(new Radius.circular(30.0)),
color: Colors.transparent,
child: new Container(
constraints: BoxConstraints.expand(height: 50),
),
),
new Container(
constraints: BoxConstraints.expand(height: 50),
decoration: BoxDecoration(
borderRadius: new BorderRadius.all(new Radius.circular(30.0)),
gradient: new LinearGradient(
colors: [color1, color2],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
child: new FloatingActionButton.extended(
backgroundColor: Colors.transparent,
foregroundColor: Colors.transparent,
highlightElevation: 0,
elevation: 0,
onPressed: () {
onPressed();
},
label: new Text(this.caption,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.body1),
),
)
],
)

Related

Flutter Card child content height is larger than its parent

I'm trying to use a GridView to handle displays for multiple Card, each Card contains of an Image. Unfortunately it turns out that the Image is taking a larger height than its parent (see attached picture for the details).
I'm pretty new to Flutter layout so any ideas why this is happening and how I can resolve this? I want the layout to be something like this:
Display 2 cards on each line.
The Card width or height should not be fixed.
The Image height should be scaled according to its width.
class SquadSelectionScreen extends StatelessWidget {
final List<Team> teams;
const SquadSelectionScreen({super.key, required this.teams});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Squads'),
),
body: GridView.count(
crossAxisSpacing: 10,
crossAxisCount: 2,
padding: const EdgeInsets.all(16),
children: teams
.map(
(team) => SquadView(team: team),
)
.toList(),
),
);
}
}
class SquadView extends StatelessWidget {
final Team team;
const SquadView({super.key, required this.team});
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
context.push('/squads/${team.code}');
},
child: Card(
elevation: 1,
child: Column(
children: [
Image(
image: NetworkImage(team.imageUrl),
),
const SizedBox(
height: 8,
),
Center(
child: Text(team.name),
),
],
),
),
);
}
}
Using GridView.count has a very visible drawback, namely the size of the aspect ratio of the grid will always be one (1:1 or Square) and can't be changed.
So if you look at the code above, you can't set an image with the same aspect ratio because the text will sink.
The first suggestion for me if you still want to use GridView.count is
Wrapping your Image with AspectRatio that has value higher than one (example set Ratio to 4/3, 5/3, 16/9, or landscape looks). Note: 4/3 = is higher than 1, 16/9 = is higher than 1, etc..
Then wrap the Text Widget with Expanded()
Example code:
class SquadView extends StatelessWidget {
final Team team;
const SquadView({super.key, required this.team});
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {},
child: Card(
elevation: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
AspectRatio(
aspectRatio: 4/3, // you can set the value to 16/9 or anything that result is higher than one
child: Image(
image: NetworkImage(team.imageUrl),
fit: BoxFit.cover, // set How the image looks to Fit
),
),
const SizedBox(
height: 8,
),
Expanded(
child: Center(
child: Text(team.name, overflow: TextOverflow.ellipsis),
),
),
],
),
),
),
);
}
}
I suggest you try GridView.builder or another GridView. You can look at the documentation here
or this third package this will be good for to try flutter_staggered_grid_view. The flutter_staggered_grid_view is more flexible to create GridView with various size.

Flutter touchable library

Good day to all. I wanted to use the touchable tool, which allows you to read clicks on the canvas, but there was an error with gesture_detector, which I don't understand how to fix. Here is the code I wrote:
Container(
child: FittedBox(
child: tooth.length == 20 && mouth != null
? SizedBox(
width: mouth?.width.toDouble(),
height: mouth?.height.toDouble(),
child: CanvasTouchDetector(
builder: (context) => CustomPaint(
painter:
FaceOutlinePainter(context),
),
))
: Text('data')),
),
And Flutter sends me to this error. As I understand it, it does not depend on CustomPaint.
throw FlutterError.fromParts(<DiagnosticsNode>[
ErrorSummary('Incorrect GestureDetector arguments.'),
ErrorDescription(
'Having both a pan gesture recognizer and a scale gesture recognizer is redundant; scale is a superset of pan.',
),
ErrorHint('Just use the scale gesture recognizer.'),
]);
I will be very grateful for your help.
With best wishes,
from Dmitry
That's because you are using one Listener per CustomPainter, you should use just one Listener for all your Stack.
And if you want to know if the current touch event is inside each Circle , you could use GlobalKeys to get the RenderBox for each Circle, then you have the renderBox, and the PointerEvent, you can easily check the HitTest, check the code:
class _MyHomePageState extends State<MyHomePage> {
GlobalKey _keyYellow = GlobalKey();
GlobalKey _keyRed = GlobalKey();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text("title"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Listener(
onPointerMove: (PointerEvent details) {
final RenderBox box = _keyRed.currentContext.findRenderObject();
final RenderBox boxYellow =
_keyYellow.currentContext.findRenderObject();
final result = BoxHitTestResult();
Offset localRed = box.globalToLocal(details.position);
Offset localYellow = boxYellow.globalToLocal(details.position);
if (box.hitTest(result, position: localRed)) {
print("HIT...RED ");
} else if (boxYellow.hitTest(result, position: localYellow)) {
print("HIT...YELLOW ");
}
},
child: Stack(
children: <Widget>[
CustomPaint(
key: _keyYellow,
painter: ShapesPainter(),
child: Container(
height: 400,
width: 400,
),
),
CustomPaint(
key: _keyRed,
painter: ShapesPainter1(),
child: Container(
height: 200,
width: 200,
),
),
],
),
),
],
),
),
);
}
}

How to fix a button at bottom of a single child scrollview with a list

I have a SingleChildScrollView and inside it I have a list with some cards, that you can remove ou add more. I need to fix an add button at the bottom of the screen, when the card list is not scrollable yet, but when the card list increase size and the scrollview is able to scroll now (to see all the content), the button must follow the list and not keep fixed at the bottom anymore.
For now, what I did to solve this, was check the scroll view every time that a card is added ou removed, if I checked that the screen is now scrollable or not scrollable I change some properties of my build widget:
SingleChildScrollView(
controller: _scrollController,
physics: AlwaysScrollableScrollPhysics(),
child: Container(
height: isNotScrollable
? _pageSize - (_appBarSize + _notifySize)
: null,
padding: const EdgeInsets.symmetric(
horizontal: Constraints.paddingNormal),
child: Column(
.....
and after the list render I create the button like this
isNotScrollable
? Expanded(
child: Container(),
)
: Container(),
CVButton(
color: Palette.white,
Basically, my idea is: if the screen is not scrollable yet (the list content fits in the screen size) I will set a height to the container inside scrollview and add a Expanded() widget before the add button (so the button will stay in the bottom of the container), but if the screen is scrollable (the list content not fits inside the screen size) so I remove the container height and the Expanded widget, then the button will follow the list now as normally.
I don't know if this is the better way to deal with that, I want to know if there is some way to do this without this 'dinamic' way that I am doing, only with fixed widgets and not changing the widget according to the state of the scrollview.
An example when the list becomes scrollable and the button will keep at list bottom
Here the list is not scrollable yet but the button must be at the screen bottom and not list bottom
(I dont wanna use bottomNavBar)
Anyone has any idea how I can solve this?
I have a solution for this. check the code bellow. I added some buttons to add or remove cards. The main trick is to use constraints like minHeight.
import 'package:flutter/material.dart';
class BottomButton extends StatefulWidget {
#override
_BottomButtonState createState() => _BottomButtonState();
}
class _BottomButtonState extends State<BottomButton> {
List<Widget> cards = [];
#override
Widget build(BuildContext context) {
var appBar2 = AppBar(
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () {
_addCard();
}),
IconButton(
icon: Icon(Icons.remove),
onPressed: () {
_removeCard();
}),
],
);
return Scaffold(
appBar: appBar2,
body: Container(
height: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top + appBar2.preferredSize.height),
alignment: Alignment.topCenter,
child: ListView(
primary: true,
children: [
Container(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top +
appBar2.preferredSize.height),
),
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height -
(MediaQuery.of(context).padding.top +
appBar2.preferredSize.height +
50),
),
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: cards,
),
),
ElevatedButton(
child: Text('this is a button'),
onPressed: () {},
),
],
),
)
],
),
),
);
}
void _addCard() {
Widget card = Card(
child: Container(
height: 100,
color: Colors.red,
padding: EdgeInsets.all(2),
),
);
setState(() {
cards.add(card);
});
}
void _removeCard() {
setState(() {
cards.removeLast();
});
}
}

Image to take the height and with of parent element

so today i did good with advancing in learning to make an app with flutter , i made a ListView , but the image didnt take the full height and with of the parent element , i tried some solutions but it didnt workout
this is the class
class FlowersItem extends StatelessWidget {
final String imgAssetPath;
FlowersItem({this.imgAssetPath});
#override
Widget build(BuildContext context) {
return Container(
width: 200,
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 30),
margin: EdgeInsets.only(right: 16),
decoration: BoxDecoration(
color: Color(0xff29404E),
borderRadius: BorderRadius.circular(12)
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(children: <Widget>[
ClipRect(
child: FittedBox(
child: Image.asset(imgAssetPath),
fit: BoxFit.fill,
),
)
],)
],
),
);
}
}
List<FlowersItem> flowers = [
FlowersItem(
imgAssetPath: 'assets/images/flower1.jpeg',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
FlowersItem(
imgAssetPath: 'assets/images/flower-pot.png',
),
];
Have you tried BoxFit.cover? I think that's what you are looking for.
It generally works for me when I want to fill out and entire box with an image.
have you tried Expanded class?
So, Expanded class is A widget that expands a child of a Row, Column, or Flex so that the child fills the available space.
you could find the documentation here.

How do I get the Yellow Container To Expand and Fill The Rest of the Space that its Purple Parents Has Available

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)),
),
],
),
),
),
),
],
),
You have to do the following changes:
1.- Replace the ConstrainedBox() with a SizedBox()
2.- Replace the last Flexible() with an Expanded(). Flexible adapts itself to the size of the container. Try it by removing the container child.
3.- And finally switch the green Container() and the yellow Container(). Otherwise the green one gets expanded.
This is the working code for the Scaffold:
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 SizedBox(
width: 125.0, // Do your calculations based on isWidthMax
height: double.infinity,
//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 Expanded(
child: new Container(
color: Colors.amberAccent,
child: sheet,
),
),
new Container(
color: Colors.greenAccent,
child: (attachment != null) ? attachment : null,
),
],
),
),
),
],
),
);
}
And this is the result