Overflow Solution: Using CustomMultiChild Layout to Resolve RenderOverflow Errors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// for Flutter Inspector layout tools: visualizing render overflow solutions | |
// This example is adapted from SO "How to use CustomMultiChildLayout & CustomSingleChildLayout in Flutter" | |
//https://stackoverflow.com/questions/59483051/how-to-use-custommultichildlayout-customsinglechildlayout-in-flutter/59483482#59483482 | |
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(ColumnOverflow()); | |
} | |
class ColumnOverflow extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: MultiChildDemo(title: 'CustomMultiChild Layout'), | |
); | |
} | |
} | |
// CustomMultiChildLayout Solution for Text Render Overflow Issues | |
class MultiChildDemo extends StatefulWidget { | |
MultiChildDemo({Key key, this.title}) : super(key: key); | |
final String title; | |
@override | |
_MultiChildDemoState createState() => _MultiChildDemoState(); | |
} | |
class _MultiChildDemoState extends State<MultiChildDemo> { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text(widget.title), | |
), | |
body: Container( | |
child: CustomMultiChildLayout( | |
delegate: YourLayoutDelegate(), | |
children: <Widget>[ | |
// Left Layout Side. | |
LayoutId( | |
// (child 1) The id can be any Object or any enum value. | |
id: 'icon_channel', | |
child: Card( | |
child: Padding( | |
padding: const EdgeInsets.all(18.0), | |
child: Icon(Icons.message), | |
), | |
), | |
), | |
// Right Layout Side. | |
LayoutId( | |
// (child2) This is the area where the text is overflowing in the sample app. | |
//To deal with overflow issues, use this id for laying out your children. | |
id: 'overflow_area', | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.start, | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text("Title", style: Theme.of(context).textTheme.headline4), | |
Text( | |
"This is the primary widget with the layout issue." | |
"The goal here is to make the widget have the text block have multilines cascading down the page , not just a single line. This shows how to deal with a large chunk of text." | |
" this is Widget Two. widget two. Widget Two. This is the primary widget." | |
"The goal here is to make the widget the prominent widget, not widget one, and no text running off the screen. " | |
"Widget Two. This is for showing proof of overflow text rendering the primary widget", | |
maxLines: 10, | |
textAlign: TextAlign.left, | |
overflow: TextOverflow.ellipsis, | |
textDirection: TextDirection.ltr, | |
style: TextStyle( | |
color: Colors.grey[800], | |
fontWeight: FontWeight.bold, | |
fontSize: 14.0), | |
), | |
], | |
), | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class YourLayoutDelegate extends MultiChildLayoutDelegate { | |
// You can pass parameters to this class because you will instantiate your delegate | |
// in the build function where you place your CustomMultiChildLayout. | |
// Note: using an Offset for this example. | |
YourLayoutDelegate({this.position}); | |
final Offset position; | |
@override | |
// `size` is the size of the `CustomMultiChildLayout` itself. | |
void performLayout(Size size) { | |
// If there is no widget with id `icon_channel`, the size will remain at zero. | |
Size leadingSize = Size.zero; | |
if (hasChild('icon_channel')) { | |
leadingSize = layoutChild( | |
'icon_channel', // child 1. | |
// Tight means the child cannot be bigger than the whole layout. | |
BoxConstraints.tightFor(height: size.height), | |
); | |
// No need to position this to have it at Offset(0, 0). | |
} | |
//This resolves the render overflow error using the box constraints and again, using tight for the flex factor. | |
if (hasChild('overflow_area')) { | |
final secondSize = layoutChild( | |
'overflow_area', | |
BoxConstraints.tightFor(width: size.width / 2), | |
); | |
positionChild( | |
'overflow_area', // child 2. | |
Offset( | |
// This will place 'overflow_area' (child 2) to the right of 'icon_channel' (child 1). | |
leadingSize.width, | |
// Centers the 'overflow_area' (child 2) vertically. | |
size.height / 2 - secondSize.height / 2, | |
), | |
); | |
} | |
} | |
@override | |
bool shouldRelayout(YourLayoutDelegate oldDelegate) { | |
return oldDelegate.position != position; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated to maintain content consistency of the example solution options for dealing with an overflow error.