Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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) result of the above code

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

like image 908
mzimmermann Avatar asked Aug 25 '17 06:08

mzimmermann


2 Answers

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'),           ],         )     ),   )); } 
like image 58
Collin Jackson Avatar answered Sep 27 '22 23:09

Collin Jackson


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);                 }               }             },           ),       );     } 
like image 36
Natwar Singh Avatar answered Sep 27 '22 22:09

Natwar Singh