Related
I have a screen that contains a Row widget with 3 Column children. I want to add a space for the first children and another space for the second children. In general, I want a screen like this:
I try with these codes but not work correctly.
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 10),
child: Column(
children: [
item(),
item(),
item(),
],
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 20),
child: Column(
children: [
item(),
item(),
item(),
],
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 5),
child: Column(
children: [
item(),
item(),
item(),
],
),
),
),
],
);
Can you help me?
Add a SizedBox to the children of the Rows, each with different height.
I hope this will help you and I just modified it with some Container().
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 10),
child: Column(
children: [
Container(
height: 50,
color: Colors.red,
),
Container(
color: Colors.red,
height: 50,
),
Container(
color: Colors.red,
height: 50,
),
],
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 20),
child: Column(
children: [
//////here you have to add SizedBox widget with different heights
const SizedBox(
height: 40,
),
Container(
color: Colors.red,
height: 50,
),
Container(
color: Colors.red,
height: 50,
),
Container(
color: Colors.red,
height: 50,
),
],
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 5),
child: Column(
children: [
Container(
color: Colors.red,
height: 50,
),
Container(
color: Colors.red,
height: 50,
),
Container(
color: Colors.red,
height: 50,
),
],
),
),
),
],
)
Output:
You can add a SizedBox between the items. Like:
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 5),
child: Column(
children: [
item(),
SizedBox(height:20),
item(),
SizedBox(height:20),
item(),
],
),
),
),
I think that is simple, but works.
You can use a Container with margins in the items too.
If you want a more complex item, you can use ListView.separated.
ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.black,
),
itemCount: 20,
itemBuilder: (context, index) => Padding(
padding: EdgeInsets.all(8.0),
child: Center(child: Text("Index $index")),
),
)
Why does the 1st two work but not the 3rd?? what's the alternative to add vertical divider with height that stretch to the max height of the row?
These 2 works
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
child: Text('Kicukiro'),
),
Container(width: 1,color: Colors.black,height: double.infinity,),
Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text('Kicukiro'),
)
],
)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Container(
child: Text('Kicukiro'),
),
),
// Container(width: 1,color: Colors.black,height: double.infinity,),
Expanded(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text('Kicukiro'),
),
)
],
)
this does not work
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Container(
child: Text('Kicukiro'),
),
),
Container(width: 1,color: Colors.black,height: double.infinity,),
Expanded(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text('Kicukiro'),
),
)
],
)
Test this and it will work
IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Container(
child: const Text("Kicukiro", style: TextStyle(fontSize: 52),)),
),
Container(color:Colors.black, width: 1),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: const Text("Kicukiro", style: TextStyle(fontSize: 52),)),
),
],
),
),
In the last screenshot please add the Container under an Expanded widget. Use children property under Row widget.
Here is an example code
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 5,
child: Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text(
'This is question',
style: TextStyle(
fontSize: 25.0,
color: Colors.white,
),
),
),
),
),
Expanded(
child: Padding(
padding: EdgeInsets.all(10.0),
child: FlatButton(
//textColor: Colors.white,
color: Colors.green,
child: Text(
'True',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
onPressed: () {},
),
)),
Expanded(
child: Padding(
padding: EdgeInsets.all(10.0),
child: FlatButton(
//textColor: Colors.white,
color: Colors.red,
child: Text(
'False',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
onPressed: () {},
),
)),
]
The third is true, in fact, its existence in an SingleChildScrollView has created a problem
It is fixed by putting SizedBox in Row and giving it height
The reason for this problem is the size of the height of the container, which is determined by double.infinity and due to its presence in an SingleChildScrollView, it continues indefinitely and an error was created.
SingleChildScrollView(
child: SizedBox(
height: 250,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: Container(child: Text("Kicukiro"))),
Container(
width: 1,color: Colors.black,height: double.infinity,
),
Expanded(child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text("Kicukiro"))),
],
),
),
),
I'm new to Flutter and have been trying to clone a screen that requires a scroll architecture.Here is the link of the screen that i'm working on. https://i.stack.imgur.com/1OW2b.pngThe code is as below.PS: Ignore the fields that are incomplete. As soon as I get the scroll view, i'll add the functionalities afterwards.
Scaffold(
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: const <Widget>[
Icon(Icons.menu),
Image(), //Asset image
],
),
Row(
children: <Widget>[
const Icon(Icons.notifications_none),
const SizedBox(width: 27.0),
CircleAvatar(
child: Text("JM"),
),
],
)
],
),
Row(
children: const <Widget>[
Icon(Icons.arrow_back),
SizedBox(width: 20.0),
Text("Public page"),
],
),
const SizedBox(
height: 20.0,
),
const Text(" Please fill the form following the proper order."),
const SizedBox(height: 10.0),
OverviewWidget(), //Widget with lots of TextFormField
SizedBox(height: 10.0),
DescriptionWidget(), //Widget with lots of TextFormField
],
),
),
Align([enter image description here][1]
alignment: Alignment.bottomCenter,
child: GestureDetector(
onTap: () {
print("Hello");
},
child: Container(
height: 130.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 10,
spreadRadius: 1,
)
],
),
child: Container(
margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
decoration: BoxDecoration(
color: Colors.green.shade400,
borderRadius: BorderRadius.circular(35),
),
child: const Padding(
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 150.0,
),
child: Text(
"Save",
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.w600),
),
),
),
),
),
),
],
),
);
So far, i've only created the Overview and Description widgets and i'm already getting RenderFlex overflow error. I tried wrapping the very first Column widget with a SingleChildScrollView widget but it can be noticed that the Save button at the bottom should stay fixed. I tried wrapping the whole widget with Stack widget instead of a Column widget but it didn't help either. I also used ListView widget but got the same results.What shall I do to achieve this view?
I guess you had all the elements but did not quite manage to use them as needed.
Your screen is composed of two important layout:
A stack (containing a button on top of a scrollable widget)
The scrollable widget
The stack has to be a stack, the scrollable can be anything but in your case SingleChildScrollView+Column seems the best choice.
Here is the concrete implementation:
Scaffold(
body: Stack(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(bottom: 100.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Icons.menu),
Container(
height: 100,
width: 100,
color: Colors.redAccent,
),
//Asset image
],
),
Row(
children: <Widget>[
const Icon(Icons.notifications_none),
const SizedBox(width: 27.0),
CircleAvatar(
child: Text("JM"),
),
],
)
],
),
Row(
children: const <Widget>[
Icon(Icons.arrow_back),
SizedBox(width: 20.0),
Text("Public page"),
],
),
const SizedBox(
height: 20.0,
),
const Text(" Please fill the form following the proper order."),
const SizedBox(height: 10.0),
Container(
height: 400,
color: Colors.blueAccent,
), //Widget with lots of TextFormField
SizedBox(height: 10.0),
Container(
height: 400,
color: Colors.greenAccent,
), //Widget with lots of TextFormField
],
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
child: GestureDetector(
onTap: () {
print("Hello");
},
child: Container(
height: 130.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 10,
spreadRadius: 1,
)
],
),
child: Container(
margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
decoration: BoxDecoration(
color: Colors.green.shade400,
borderRadius: BorderRadius.circular(35),
),
child: const Padding(
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 150.0,
),
child: Text(
"Save",
style: TextStyle(
color: Colors.white, fontSize: 17, fontWeight: FontWeight.w600),
),
),
),
),
),
),
],
),
)
Note that you have to put a bottom padding inside the SingleChildScrollView to take into account the button. This is fine in your case since the button has a static height. However if you need something more fancy you might want to check How to create a scroll view with fixed footer with Flutter? as #Csisanyi suggested
Consider wrapping the Column with an Expanded widget
You can also check out this flutter doc. It addresses this common issue in detail.
https://flutter.dev/docs/testing/common-errors
Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(15.0, 40.0, 15.0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Icons.menu),
// Image(), //Asset image
Image.asset(
'assets/ocean.jpg',
height: kToolbarHeight,
/// make sure of image height
fit: BoxFit.fitHeight,
),
],
),
Row(
children: <Widget>[
const Icon(Icons.notifications_none),
const SizedBox(width: 27.0),
CircleAvatar(
child: Text("JM"),
),
],
)
],
),
Row(
children: const <Widget>[
Icon(Icons.arrow_back),
SizedBox(width: 20.0),
Text("Public page"),
],
),
const SizedBox(
height: 20.0,
),
const Text(
" Please fill the form following the proper order."),
const SizedBox(height: 10.0),
//todo: OverviewWidget(), //Widget with lots of TextFormField
...List.generate(22, (index) {
return TextField(
decoration: InputDecoration(hintText: "1st $index"),
);
}),
SizedBox(height: 10.0),
//todo: DescriptionWidget(), //Widget with lots of TextFormField
...List.generate(22, (index) {
return TextField(
decoration: InputDecoration(hintText: "2st $index"),
);
}),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: GestureDetector(
onTap: () {
print("Hello");
},
child: Container(
height: 130.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 10,
spreadRadius: 1,
)
],
),
child: Container(
margin: const EdgeInsets.only(top: 10.0, bottom: 30.0),
decoration: BoxDecoration(
color: Colors.green.shade400,
borderRadius: BorderRadius.circular(35),
),
child: const Padding(
padding: EdgeInsets.symmetric(
vertical: 15.0,
horizontal: 150.0,
),
child: Text(
"Save",
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.w600),
),
),
),
),
),
),
],
),
),
),
I'm trying to personalize what's inside a RaisedButton for my home automation project, in with I add different types of text and icons to the Button. but I'm getting an overflow by 1 pixel for some reason.
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: SizedBox(
width: 90.0,
height: 90.0,
child: RaisedButton(
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(Icons.stay_primary_portrait),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 0),
child: Text('Lock'),
),
Padding(
padding: EdgeInsets.only(left: 0),
child: Text('100%'),
),
],
),
],
),
),
),
),
The app:
The RaisedButton has some default padding. Fix it by removing the default padding.
This would work perfectly, check it out.
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: SizedBox(
width: 90.0,
height: 90.0,
child: RaisedButton(
// remove the default padding the raised button has
padding: EdgeInsets.zero,
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(Icons.stay_primary_portrait),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 0),
child: Text('Lock'),
),
Padding(
padding: EdgeInsets.only(left: 0),
child: Text('100%'),
),
],
),
],
),
),
),
),
The output looks like this
Screenshot
I didn't figure out why you get this result but you can use InkWell + Container instead of RaisedButton:
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: SizedBox(
width: 90.0,
height: 90.0,
child: InkWell(
onTap: () {},
child: Container(
color: Colors.grey,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(Icons.stay_primary_portrait),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 0),
child: Text('Lock'),
),
Padding(
padding: EdgeInsets.only(left: 0),
child: Text('100%'),
),
],
),
],
),
),
),
),
),
Need to help to copy the layout on image below.
2 buttons with 50% width and padding/spacing in between.
I'm thinking also of using toggle button widget on it.
see my draft code below.
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
children: <Widget>[
Container(
color: Colors.green,
width: (MediaQuery.of(context).size.width) / 2.5,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
MdiIcons.account,
size: 18.0,
),
SizedBox(
width: 4.0,
),
Text(
"Client",
style: TextStyle(fontSize: 16),
)
],
)),
Container(
color: Colors.green,
width: (MediaQuery.of(context).size.width) / 2.5,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
MdiIcons.accountTie,
size: 18.0,
),
SizedBox(
width: 4.0,
),
Text(
"Host",
style: TextStyle(fontSize: 16),
)
],
)),
],
),
),
You can customize it,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
onPressed: () {},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
elevation: 1.5,
color: Colors.white,
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Icon(Icons.developer_board),
SizedBox(height: 10),
Text("Experiences"),
],
),
),
),
SizedBox(width: 24),
Expanded(
child: RaisedButton(
onPressed: () {},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
elevation: 1.5,
color: Colors.white,
padding: const EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Icon(Icons.event),
SizedBox(height: 10),
Text("Events"),
],
),
),
),
],
),
),