Hi I'm new to Flutter and I got in trouble with the exception "RenderBox was not laid out".
I'm trying to create MyDialog which is an extension of the built-in dialog.
It can be injected contents from other widget. And I wanna place Expanded widget wrapping Text widget as the contents so that all text can be seen with line breaks.
I intent the contents show like this:
This is my MyDialog widget.
class MyDialog extends StatelessWidget {
String label;
Widget contents;
const MyDialog({required this.label, required this.contents, Key? key}) : super(key : key)
#override
Widget build(BuildContext context) {
return MyButtonTip( // This is an extension of outlined button.
label : label,
onPressed : () {
showDialog(
context : context,
builder : (BuildContext context) => AlertDialog(
insetPadding : const EdgeInsets.all(15),
content : SizedBox(
width : MediaQuery.of(context).size.width,
child : contents
)
)
);
}
);
}
}
And this is the widget that uses MyDialog.
...
MyDialog(
label : 'Profile',
contents : SizedBox(
child : Stack(
children : [
Column(
children : [
Row(
children : [
Column(
crossAxisAlignment : CrossAxisAlignment.end,
children : const [
Text('name'),
Text('nickname')
]
),
const SizedBox(width : 10),
Column(
crossAxisAlignment : CrossAxisAlignment.start,
children : [
Text(name),
Expanded(
child : Text(nickname)
)
]
)
]
)
]
)
]
))
)
);
...
(I'm using Stack for aiming something different, so please don't care about it.)
I would like to know the correct solution, as I have encountered this exception many times before and each time it has somehow been resolved. Please let me know in detail.
Thanks,
PS. console:
As my opinion you placed widget wrong please try with below code :
MyDialog(
label : 'Profile',
contents : Column(children: [
Row(children: const [
Text('name : '),
Text("hello"),
]),
const SizedBox(width: 10),
Row(crossAxisAlignment: CrossAxisAlignment.start, children: const [
Text('taro yamuda : '),
Expanded(
child: Text(
"someting sometingsometingsometingsometingsometingsometingsometingsometingsometingsometingsometingsometing",
style: TextStyle(),
),
)
])
]);
}
Related
import 'package:flutter/material.dart';
class DetailsScreen extends StatefulWidget {
final int index;
const DetailsScreen({Key? key, required this.index}) : super(key: key);
#override
State<DetailsScreen> createState() => _DetailsScreenState();
}
class _DetailsScreenState extends State<DetailsScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Hero(
tag: widget.index,
child: Image.network(
"https://raw.githubusercontent.com/markknguyen/pictures/master/pic/${widget.index + 1}.png",
),
const Text("Rome"),
),
),
);
}
}
I tried adding const thinking it will resolve the issue but I didn't. The code did not run. I Just wanted to add some sort of text box in a page. const Text("Rome"), is the main concern.
You can't just have your Text widget there with no parent. You need to put your Hero and Text widget in a Column like so:
Center(
child: Column(
children: [
Hero(
tag: widget.index,
child: Image.network(
"https://raw.githubusercontent.com/markknguyen/pictures/master/pic/${widget.index + 1}.png",
),
),
Text("Rome"),
],
),
),
or any other Widget that acceptes multiple children such as Row or ListView based on your needs
The issue is that your Text() widget isn't passed as a parameter. Currently, the code can't compile due to treating your Text("Rome") as a 'mistake', sort of speaking.
Depending on your use-case scenario, you can either use:
a Column() - if you want your widgets to be one after another in a column.
a Stack() - if you want your widgets to be placed one under another.
You'll have to pass the children attribute to both, so for example:
Column(
children: [
Image.network(
"https://raw.githubusercontent.com/markknguyen/pictures/master/pic/${widget.index + 1}.png",
),
const Text("Rome"),
]
)
I want make text to the right, what am I doing so far
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _judul = 'Private Chat';
static var _warnaTema = Colors.pink[100];
Widget _dummyExpanded() {
return Expanded(
child: Container(), //contain empty data,
); //just for fill remaining space
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _judul,
theme: ThemeData(
primaryColor: _warnaTema,
),
home: Column(
children: [
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 1'),
],
),
),
Container(
child: Row(
children: [
this._dummyExpanded(),
Text('this is real data 2'),
],
),
)
],
),
);
}
}
The layout output is what I expected (the text is in right), however there's unneeded code.
As you see I use unnecessary method _dummyExpanded to fill
available space which it's just expanded with empty container. Of course it will be hard to read since there are many nested row and column, how I remove that unneeded method without loss layout output what I expect?
I believe I should have use alignment but I don't know how to
Method 1.
Container(
child: Row(
mainAxisAlignment:MainAxisAlignment.end,
children: [
Text('this is real data 2'),
],
),
)
Method 2.
I prefer this method, You can wrap text with this method.
You can also use Flexible widget instead of Expanded
Container(
child: Row(
children: [
Expanded(child: Text('this is real data 2', textAlign:TextAlign.end )),
],
),
)
Method 3.
If you have only Text widgets as children of Column widget then you can set crossAxisAlignment: CrossAxisAlignment.end, for your parent Column widget.
I'm already losing sleep over this.
I'm trying to display a chart inside a ListView (for scrolling). For some reason the contents of the Card flickers when scrolling and randomly completely disappears (the Card itself stays visible though).
Any idea why would that happen?
(...) ListView (...)
children: [Row ( children: [buildChartBox()] )] (...)
Expanded buildChartBox() {
return Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
chartTitles(
title: 'Items',
subtitle: 'by value'),
SizedBox(
height: 300,
child: ValuesChart(data: calculateValues(items)))
],
),
],
),
),
),
);
}
Row chartTitles({String title = '', String subtitle = ''}) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: text_charttitle),
Text(subtitle, style: text_chartsubtitle),
],
)
],
);
}
Things tried:
Both of these were originally Stateless Widgets; I changed to simple
methods to simplify but it didn't change the weird behaviour.
Replacing the chartTitles return with an empty Container (i.e. removing the titles) does mitigate the issue. The chart then stays displayed but also flickers slightly.
Replacing the ListView with a SingleChildScrollView doesn't change anything.
EDIT: Code for the ValuesChart:
import 'package:fl_chart/fl_chart.dart';
class ValuesChart extends StatelessWidget {
final Map<String, int> data;
const ValuesChart({required this.data});
#override
Widget build(BuildContext context) {
return Container(
child: PieChart(
_theData(data),
));
}
}
Note I'm using a package called 'fl_chart'. _theData just returns various parameters for the chart, I don't think it's relevant.
Try to replace ListView with SingleChildScrollView
ListViews in flutter by default using what it is called in Android RecyclerView to efficiently use render resources.
If you are interested here an article
https://medium.com/1mgofficial/how-recyclerview-works-internally-71290de5d2c4
How to place a Widget below fixed Centered Widget inside a Container? I am using a GridView to show widgets horizontally. GridView item will have a Text Widget which has to be fixed at the Centered everytime in the screen. I have to place a Text widget below that Centered Widget.
Reference Screenshot:
Adding the build method code of the GridView item I have tried till now. But the Text Widget is not getting centered. The output I am getting. How to fix this part ?
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CustomText(
(dayModel?.date?.day ?? "").toString(),
AppTextStyle.Body,
customColor: _getColorBasedOnStyle(
dayModel.style,
),
),
Visibility(
visible: dayModel?.style == CalendarDayStyles.NOT_AVAILABLE,
child: CustomText(
Strings.no_slots_label,
AppTextStyle.SublineForCalendar,
customColor: AppColors.BLACK_20,
),
),
],
);
}
I believe the secret to doing this right is not only in how you build "6", but also in how you build "5" and "7".
E.g. you could build every one of them as column with 3 boxes on top of each other, pseudocode:
Column(
children: [
SizedBox(height: fixedHeight, child: empty)
SizedBox(height: fixedHeight, child: Text("5")) // or "6" or "7"
SizedBox(height: fixedHeihgt, child: empty) // or booking status
]
)
or other way of doing it if we have to avoid using fixedHeight is by using the Expanded Widget inside the Column Widget
Column(
children: [
Expanded(child: Container()),
Expanded(child: Center(child : Text("5"))), // or "6" or "7"
Expanded(child: Center(child : Text("No Slots"))) // or booking status
]
)
If you set crossAxisAlignment of the row to start and then show a column with "no slots" underneath, shouldn't this fix your issue?
You could use the CrossAxisAlignment.center:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
),
Full snippet code:
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
CustomText(
(dayModel?.date?.day ?? "").toString(),
AppTextStyle.Body,
customColor: _getColorBasedOnStyle(
dayModel.style,
),
),
Visibility(
visible: dayModel?.style == CalendarDayStyles.NOT_AVAILABLE,
child: CustomText(
Strings.no_slots_label,
AppTextStyle.SublineForCalendar,
customColor: AppColors.BLACK_20,
),
),
],
);
I have a certain Text widget , when it overflows I have 3 options. Either fade ,visible, ellipsis or clip. But I don't want to choose between them . I want if a text has overflow then don't show the text.
Edit :
I'm working on a code clone to this design
Assuming that the textStyle is unknown.
How could I achieve that?
Code:
class SwipeNavigationBar extends StatefulWidget {
final Widget child;
SwipeNavigationBar({this.child});
#override
_SwipeNavigationBarState createState() => _SwipeNavigationBarState();
}
class _SwipeNavigationBarState extends State<SwipeNavigationBar> {
#override
Widget build(BuildContext context) {
return Consumer<Controller>(
builder: (_, _bloc, __) {
return SafeArea(
child: AnimatedContainer(
duration: Duration(seconds: 01),
color: Colors.white,
curve: Curves.easeIn,
height: !_bloc.x ? 50 : 200,
child: Row(
children: [
Column(
verticalDirection: VerticalDirection.up,
children: [
Expanded(child: Icon(Icons.dashboard)),
Expanded(
child: RotatedBox(
quarterTurns: -45,
child: Text(
'data',
softWrap: false,
style: TextStyle(
textBaseline: TextBaseline.alphabetic
),
),
),
),
],
)
],
),
),
);
},
);
}
}
To mimic the design you might want to look into using the Stack widget. However, to answer your question, you'd want to set softWrap to false.
Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: 100,
child: Text(
'Some text we want to overflow',
softWrap: false,
),
),
)
softWrap is really the key here. Although, I added the Align and SizedBox widgets to allow this to be used anywhere, regardless of what parent widget you are using (since some widgets set tight constraints on their children and will override their children's size preference).
CodePen Example
Edit: 5/6/2020
With the release of Flutter v1.17 you now have access to a new Widget called NavigationRail which may help you with the design you're looking for.
Use ternary operator to check the length of the text that you are passing to the Text widget and based on that pass the text itself or an empty string.
String yourText;
int desiredLengthToShow = 10; //Change this according to you.
...
Text(
child: yourText.length > desiredLengthToShow ? "" : yourText,
);