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); } } }, ), ); }
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