I'm trying to get a chart from the charts_flutter package to expand to fill available space, when it is inside a Row which is inside a Column. I've spent a couple of hours trying to do this but I must be missing something! This is visually what I'm trying to achieve:
Here's a minimal working example. I must have tried a hundred combinations of Expanded, Flexible, main axis size, cross axis alignment etc. but I just can't seem to find the correct one. Currently the bottom overflows by infinity pixels, with object was given an infinite size during layout
. There is this open issue , I don't know if it's related, and there is no answer. I just need help with the bit of code inside runApp
:
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
void main() => runApp(
// HOW DO I LAY THIS OUT?
Column(
children: <Widget>[
Container(height: 200, color: Colors.orange),
Row(
textDirection: TextDirection.ltr,
children: <Widget>[
Container(width: 200,color: Colors.orange),
Expanded(child: SimpleTimeSeriesChart.withSampleData())
],
)
],
)
);
class SimpleTimeSeriesChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
SimpleTimeSeriesChart(this.seriesList, {this.animate});
factory SimpleTimeSeriesChart.withSampleData() {
return new SimpleTimeSeriesChart(
_createSampleData(),
animate: false,
);
}
@override
Widget build(BuildContext context) {
return new charts.TimeSeriesChart(
seriesList,
animate: animate,
dateTimeFactory: const charts.LocalDateTimeFactory(),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
final data = [
new TimeSeriesSales(new DateTime(2017, 9, 19), 5),
new TimeSeriesSales(new DateTime(2017, 9, 26), 25),
new TimeSeriesSales(new DateTime(2017, 10, 3), 100),
new TimeSeriesSales(new DateTime(2017, 10, 10), 75),
];
return [
new charts.Series<TimeSeriesSales, DateTime>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: data,
)
];
}
}
class TimeSeriesSales {
final DateTime time;
final int sales;
TimeSeriesSales(this.time, this.sales);
}
**see why at Step 8 - scroll down👇 **
I'm trying to get a chart from the charts_flutter package to expand to fill available space
object was given an infinite size during layout
Wrap the Row with Expanded
Column(children: <Widget>[Expanded(child: Row())])
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
void main() => runApp(
// HOW DO I LAY THIS OUT?
Column(
children: <Widget>[
Container(height: 200, color: Colors.orange),
Expanded(
child: Row(
textDirection: TextDirection.ltr,
children: <Widget>[
Container(width: 200, color: Colors.green),
Expanded(child: SimpleTimeSeriesChart.withSampleData()),
],
),
)
],
));
class SimpleTimeSeriesChart extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
SimpleTimeSeriesChart(this.seriesList, {this.animate});
factory SimpleTimeSeriesChart.withSampleData() {
return new SimpleTimeSeriesChart(
_createSampleData(),
animate: false,
);
}
@override
Widget build(BuildContext context) {
return new charts.TimeSeriesChart(
seriesList,
animate: animate,
dateTimeFactory: const charts.LocalDateTimeFactory(),
);
}
/// Create one series with sample hard coded data.
static List<charts.Series<TimeSeriesSales, DateTime>> _createSampleData() {
final data = [
new TimeSeriesSales(new DateTime(2017, 9, 19), 5),
new TimeSeriesSales(new DateTime(2017, 9, 26), 25),
new TimeSeriesSales(new DateTime(2017, 10, 3), 100),
new TimeSeriesSales(new DateTime(2017, 10, 10), 75),
];
return [
new charts.Series<TimeSeriesSales, DateTime>(
id: 'Sales',
colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
domainFn: (TimeSeriesSales sales, _) => sales.time,
measureFn: (TimeSeriesSales sales, _) => sales.sales,
data: data,
)
];
}
}
class TimeSeriesSales {
final DateTime time;
final int sales;
TimeSeriesSales(this.time, this.sales);
}
I/flutter ( 4228): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 4228): ════════════════════════════════════════════════════════════════════════════════════════════════════
scan the error with your eyes you will see some phrases like
I/flutter ( 4228): constraints: BoxConstraints(w=320.0, h=480.0)
I/flutter ( 4228): The following assertion was thrown during performLayout():
I/flutter ( 4228): Summary 1: RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
this is a box constraints error
read more :
go near the end it will give you the source:
I/flutter ( 4228): creator: CustomMultiChildLayout ← TimeSeriesChart ← SimpleTimeSeriesChart ← Expanded ← Row ← Column
I/flutter ( 4228): ← [root]
go near the end it will give you the missing constraint
I/flutter ( 4228): constraints: BoxConstraints(w=120.0, 0.0<=h<=Infinity)
notice : 0.0<=h<=Infinity
the height can't be Infinity
warp the source with a SizedBox to make sure it' what throwing the error , to see if it solve it
A box with a specified size.
If given a child, this widget forces its child to have a specific width and/or height (assuming values are permitted by this widget's parent). If either the width or height is null, this widget will size itself to match the child's size in that dimension.
the TimeSeriesChart(child) asked Raw(parent) for height
the Raw(child) asked Column(parent) for height
the Column doesn't know
by why the Column doesn't know, because by default behavior is that it will leave it for the children to decide thir own height
but we can tell the Column that the children doesn't know so expand them to the available space
I/flutter ( 4228): ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter ( 4228): The following assertion was thrown during performLayout():
I/flutter ( 4228): FlutterError contained multiple error summaries.
I/flutter ( 4228): All FlutterError objects should have only a single short (one line) summary description of the
I/flutter ( 4228): problem that was detected.
I/flutter ( 4228): Malformed FlutterError:
I/flutter ( 4228): RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
I/flutter ( 4228): This probably means that it is a render object that tries to be as big as possible, but it was put
I/flutter ( 4228): inside another render object that allows its children to pick their own size.
I/flutter ( 4228): RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
I/flutter ( 4228): This probably means that it is a render object that tries to be as big as possible, but it was put
I/flutter ( 4228): inside another render object that allows its children to pick their own size.
I/flutter ( 4228): The nearest ancestor providing an unbounded height constraint is: RenderFlex#d29e7 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE:
I/flutter ( 4228): creator: Column ← [root]
I/flutter ( 4228): parentData: <none>
I/flutter ( 4228): constraints: BoxConstraints(w=320.0, h=480.0)
I/flutter ( 4228): size: MISSING
I/flutter ( 4228): direction: vertical
I/flutter ( 4228): mainAxisAlignment: start
I/flutter ( 4228): mainAxisSize: max
I/flutter ( 4228): crossAxisAlignment: center
I/flutter ( 4228): verticalDirection: down
I/flutter ( 4228): The constraints that applied to the RenderCustomMultiChildLayoutBox were:
I/flutter ( 4228): BoxConstraints(w=120.0, 0.0<=h<=Infinity)
I/flutter ( 4228): The exact size it was given was:
I/flutter ( 4228): Size(120.0, Infinity)
I/flutter ( 4228): See https://flutter.dev/docs/development/ui/layout/box-constraints for more information.
I/flutter ( 4228):
I/flutter ( 4228): The malformed error has 2 summaries.
I/flutter ( 4228): Summary 1: RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
I/flutter ( 4228): Summary 2: RenderCustomMultiChildLayoutBox object was given an infinite size during layout.
I/flutter ( 4228):
I/flutter ( 4228): This error should still help you solve your problem, however please also report this malformed error
I/flutter ( 4228): in the framework by filing a bug on GitHub:
I/flutter ( 4228): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 4228):
I/flutter ( 4228): When the exception was thrown, this was the stack:
I/flutter ( 4228): #0 new FlutterError.fromParts.<anonymous closure> (package:flutter/src/foundation/assertions.dart:540:9)
I/flutter ( 4228): #1 new FlutterError.fromParts (package:flutter/src/foundation/assertions.dart:543:6)
I/flutter ( 4228): #2 RenderBox.debugAssertDoesMeetConstraints.<anonymous closure> (package:flutter/src/rendering/box.dart:1966:28)
I/flutter ( 4228): #3 RenderBox.debugAssertDoesMeetConstraints (package:flutter/src/rendering/box.dart:2029:6)
I/flutter ( 4228): #4 RenderBox.size=.<anonymous closure> (package:flutter/src/rendering/box.dart:1740:7)
I/flutter ( 4228): #5 RenderBox.size= (package:flutter/src/rendering/box.dart:1742:6)
I/flutter ( 4228): #6 RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:355:5)
I/flutter ( 4228): #7 RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter ( 4228): #8 RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:805:17)
I/flutter ( 4228): #9 RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter ( 4228): #10 RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:743:15)
I/flutter ( 4228): #11 RenderObject.layout (package:flutter/src/rendering/object.dart:1619:7)
I/flutter ( 4228): #12 RenderView.performLayout (package:flutter/src/rendering/view.dart:151:13)
I/flutter ( 4228): #13 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1496:7)
I/flutter ( 4228): #14 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:765:18)
I/flutter ( 4228): #15 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:346:19)
I/flutter ( 4228): #16 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:701:13)
I/flutter ( 4228): #17 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:285:5)I/flutter ( 4228): #18 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1016:15)
I/flutter ( 4228): #19 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:958:9)
I/flutter ( 4228): #20 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:784:7)
I/flutter ( 4228): #29 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:382:19)
I/flutter ( 4228): #30 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
I/flutter ( 4228): #31 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)
I/flutter ( 4228): (elided 8 frames from package dart:async and package dart:async-patch)
I/flutter ( 4228):
I/flutter ( 4228): The following RenderObject was being processed when the exception was fired: RenderCustomMultiChildLayoutBox#e4ae0 relayoutBoundary=up2 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE:
I/flutter ( 4228): creator: CustomMultiChildLayout ← TimeSeriesChart ← SimpleTimeSeriesChart ← Expanded ← Row ← Column
I/flutter ( 4228): ← [root]
I/flutter ( 4228): parentData: offset=Offset(0.0, 0.0); flex=1; fit=FlexFit.tight (can use size)
I/flutter ( 4228): constraints: BoxConstraints(w=120.0, 0.0<=h<=Infinity)
I/flutter ( 4228): size: Size(120.0, Infinity)
I/flutter ( 4228): This RenderObject had the following descendants (showing up to depth 5):
I/flutter ( 4228): child 1: RenderSemanticsGestureHandler#2034c NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter ( 4228): child: RenderPointerListener#aef29 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
I/flutter ( 4228): child: ChartContainerRenderObject<DateTime>#b28fc NEEDS-LAYOUT NEEDS-PAINT
I/flutter ( 4228): ════════════════════════════════════════════════════════════════════════════════════════════════════
but if it does not have a height it will ask it's parent, the row
but the row dosnt have a fixed height it will ask the children
but the children don't have a fixed height it will ask the row parent
but the parent doesn't have a fixed height for it children (the row)
Just wrap your Row
in an Expanded
widget and that's it.
Column(
children: <Widget>[
Container(height: 200, color: Colors.orange),
Expanded(
child: Row(
textDirection: TextDirection.ltr,
children: <Widget>[
Container(width: 200,color: Colors.orange),
Expanded(child: SimpleTimeSeriesChart.withSampleData())
],
)
)
],
)
Explanation is that the Column
when created will provide infinity constraints to its children and when you wrap any child in a Flexible
widget, it will act accordingly to the available space (and some of the properties, if any).
The Row
acts exactly the same way, but horizontally. Here, you are properly adding the Expanded
to the Row
child, but then, it tries to find how much cant it expand to size itself, and the Row
doesn't know because it still has an unbounded height from the parent ( Column
), that's why you should use the Expanded
or even a Flexible
if you don't need to fit the available space.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.