How to align iconbuttons in card widget flutter? - flutter

I am having trouble issues aligning my icon buttons to the middle of the card. As you can see in the picture, the icon buttons are on top attached to the top of the card.
How do I make it meet at the half size of the card? Any suggestions? (I want the buttons to be located at the middle of the card)
Tried: I tried putting padding or wrap my Row widget with a center, but it doesn't work.
child: new Container(
height: 150.0,
width: MediaQuery.of(context).size.width,
child: new Card(
color: Colors.white,
elevation: 8.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children: [
IconButton(
onPressed: () {},
icon: Icon(Icons.sticky_note_2),
iconSize: 35,
color: Colors.lightBlue),
Text(
"Notes",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
Column(
children: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => QuizRoute()),
);
},
icon: Icon(Icons.quiz),
iconSize: 35,
),
Text(
"Quizzes",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
Column(
children: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EbooksRoute()),
);
},
icon: Icon(Icons.auto_stories),
iconSize: 35,
),
Text(
"Ebooks",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
]),
),
),
),
],
),

Try below code and set mainAxisAlignment: MainAxisAlignment.center, to every Column widget. Refer layout and Align
Container(
height: 150.0,
width: MediaQuery.of(context).size.width,
child: Card(
color: Colors.white,
elevation: 8.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {},
icon: Icon(Icons.sticky_note_2),
iconSize: 35,
color: Colors.lightBlue),
Text(
"Notes",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {},
icon: Icon(Icons.quiz),
iconSize: 35,
),
Text(
"Quizzes",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {},
icon: Icon(Icons.auto_stories),
iconSize: 35,
),
Text(
"Ebooks",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
],
),
),
),
Result Screen->

What is the issue?
You are using center alignment in the row but not inside the column. Now column is taking the height of entire row but the children of the column is not aligned center.
Solution:
Try adding mainAxisAlignment: MainAxisAlignment.center in each of your column
Present Code:
Row
mainAxisAlignment:MainAxisAlignment.center
|_Column
|_Column
|_Column
Required Code:
Row
mainAxisAlignment:MainAxisAlignment.center
|_Column
mainAxisAlignment:MainAxisAlignment.center 👈 Add these to every column
|_Column
mainAxisAlignment:MainAxisAlignment.center
|_Column
mainAxisAlignment:MainAxisAlignment.center
For the complete code refer : #Ravindra's answer

Replace your "Row" widget with the following code, this will solve your issue.
Solution : Give your Column center alignment
mainAxisAlignment: MainAxisAlignment.center
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.sticky_note_2),
iconSize: 35,
color: Colors.lightBlue),
const Text(
"Notes",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => QuizRoute()),
// );
},
icon: const Icon(Icons.quiz),
iconSize: 35,
),
const Text(
"Quizzes",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => EbooksRoute()),
// );
},
icon: const Icon(Icons.auto_stories),
iconSize: 35,
),
const Text(
"Ebooks",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
),
],
),
]),

Related

title widget to be centered and icon widgets at the right side in one row

the question is exactly same as this post
but I did not find an answer from the post.
my goal is to set the title widget in the center
and other two buttons on the right side.
the solutions in the link all put the title widget slightly on the left side.
does anyone know how to do this without using Stack? I'm afraid of the title widget being over the button widgets when the title gets too long.
the code:
SizedBox(
height: 40,
width: MediaQuery.of(context).size.width,
child: Row(
children: [
const SizedBox(width: 17),
Text(
'TITLE',
style: const TextStyle(
color: Colors.white, fontSize: 30, fontWeight: FontWeight.w500),
),
Spacer(),
Row(
children: [
GestureDetector(
onTap: (){null;},
child: SizedBox(
child: Icon(Icons.wallet_membership, color: Colors.white),
),
),
const SizedBox(width: 17),
GestureDetector(
onTap: (){Get.toNamed('/wallet_setting');},
child: const SizedBox(
child: Icon(Icons.settings, color: Colors.white),
),
),
]
)
]
),
)
Try this One
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: Container(
child: Center(
child: Text(
'TITLE',
style: const TextStyle(color: Colors.white, fontSize: 30, fontWeight: FontWeight.w500),
),
)
)
),
Align(
alignment: Alignment.centerRight,
child: Row(
children: [
GestureDetector(
onTap: (){null;},
child: SizedBox(
child: Icon(Icons.wallet_membership, color: Colors.white),
),
),
const SizedBox(width: 17),
GestureDetector(
onTap: (){Get.toNamed('/wallet_setting');},
child: const SizedBox(
child: Icon(Icons.settings, color: Colors.white),
),
),
]
)
)
],
)
OutPut:
i think you should wrap it with centre
Try this approach:
first make widget from your right widgets:
Widget _rightIcons() {
return Row(children: [
GestureDetector(
onTap: () {
null;
},
child: SizedBox(
child: Icon(Icons.wallet_membership, color: Colors.white),
),
),
const SizedBox(width: 17),
GestureDetector(
onTap: () {
Get.toNamed('/wallet_setting');
},
child: const SizedBox(
child: Icon(Icons.settings, color: Colors.white),
),
),
]);
}
then build your header like this:
Row(
children: [
_rightIcons(),
Expanded(
child: Center(
child: Text(
'TITLE',
style: const TextStyle(
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.w500),
),
),
),
Opacity(
opacity: 0,
child: _rightIcons(),
)
],
),
You can use centerTitle:true on Appbar
appBar: AppBar(
centerTitle: true,
title: Text("title"),
actions: [
Another way
Container(
color: Colors.purple,
height: 40 * 2,
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconButton(onPressed: () {}, icon: Icon(Icons.navigate_before)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: SizedBox(),
),
Expanded(
flex: 4,
child: Text(
'TITLE',
textAlign: TextAlign.center,
style: const TextStyle(
color: Colors.white,
fontSize: 30,
fontWeight: FontWeight.w500),
),
),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
child: Icon(Icons.wallet_membership,
color: Colors.white),
),
const SizedBox(width: 17),
GestureDetector(
onTap: () {},
child: const SizedBox(
child:
Icon(Icons.settings, color: Colors.white),
),
),
]),
),
)
],
),
],
),
)
Preferable solution:
You can implements PreferredSizeWidget to create custom Appbar. Play with color and other decoration.
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
const MyAppBar({super.key});
#override
Widget build(BuildContext context) {
return Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: Text("title"),
),
Align(
alignment: Alignment.bottomRight,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
//you can use callback method to get onpressed
onPressed: () {},
icon: Icon(Icons.settings),
),
IconButton(
onPressed: () {},
icon: Icon(Icons.settings),
),
],
),
)
],
);
}
#override
Size get preferredSize => const Size.fromHeight(kToolbarHeight * 2);
}
And use like appBar: MyAppBar(),

A RenderFlex overflowed by 1.3 pixels on the right

Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
Cart().freeDeliveryString,
style: Theme.of(context).textTheme.headline4,
),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/');
},
style: ElevatedButton.styleFrom(
primary: Colors.black,
shape: RoundedRectangleBorder(),
elevation: 0,
),
child: Text(
'Add More İtems',
style:
Theme.of(context).textTheme.headline4!.copyWith(
color: Colors.white,
),
),
),
],
),
],
),
Try wrapping any or both children of your row with an Expanded widget
Wrapping only your Text widget with an Expanded widget will be enough to solve your error.
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
'Cart().freeDeliveryString',
style: Theme.of(context).textTheme.headline4,
),
),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, '/');
},
style: ElevatedButton.styleFrom(
primary: Colors.black,
shape: RoundedRectangleBorder(),
elevation: 0,
),
child: Text(
'Add More İtems',
style: Theme.of(context).textTheme.headline4!.copyWith(
color: Colors.white,
),
),
),
],
),
],
);

Flutter Dart: Allign Row Widgets at bottom

I am new to Flutter, I am trying to show two buttons in a row at the bottom,
I have tried all possible solutions, including Align, Expanded etc but it didn't work..
Please if someone can help, as my buttons don't go at the bottom of screen
Here's my code:
return Scaffold(
body: SingleChildScrollView(
child: Column(children: [
Container(
//code
),
Container(
//code
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Intro()),
);
},
),
),
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Intro()),
);
},
),
),
],
),
]),
),
);
Here is a solution involving the bottomNavigationBar property of the Scaffold widget where you can put any Widget? (here, we're using your Row):
You can play around with the provided code on this dartpad.
Here's the result:
return Scaffold(
bottomNavigationBar: Padding(
padding: EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {},
),
),
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {},
),
),
],
),
),
body: SingleChildScrollView(
child: Column(children: [
Container(
//code
),
Container(
//code
),
]),
),
);
Here is your updated code, Please check
Scaffold(
body: Column(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
SingleChildScrollView(
child: Column(
children: [
Container(
//code
),
Container(
//code
),
],
),
),
Row(
children: [
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Intro()),
);
},
),
),
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Intro()),
);
},
),
),
],
),
]),
),
OR
You can use bottomSheet method of scaffold
Scaffold(
bottomSheet: Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Intro()),
);
},
),
),
SizedBox(width: 50),
ConstrainedBox(
constraints: BoxConstraints.tightFor(width: 100, height: 80),
child: ElevatedButton(
child: Text(
'Register',
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
),
style: ElevatedButton.styleFrom(
primary: Colors.blue.shade900,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Intro()),
);
},
),
),
],
),
),
body: SingleChildScrollView(
child: Column(children: [
Column(
children: [
Container(
//code
),
Container(
//code
),
],
),
]),
),
),
The row will match its childrens height so because all buttons have the same height your final row is 80 (px) in height and therefore it doesnt matter where to align buttons. You can wrap your row in a container with color to see it.
The corruct solution would be to give the row height by wrapping it in a diffrent widget (like column) and stretch it to available space. Then inside the row you just need CrossAxisAlignment.end. But this depends on your layout.
For example:
Column(
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
row: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
/* Buttons here **/
]),
)
]
)
You can also refer to the flutter layout guide and CSS Flexbox as it almost translates 1-1 to flutter and

align widgets to the left and right of the screen in flutter

i am having problems trying to align my widgets. the left side is aligning correctly but the right side is off a little bit.
here is my code
this is the code for the card view
ListView itemList(List<IncomeData> items, AppDatabase database, BuildContext context) {
return ListView(
children: items.map((IncomeData income) {
return Container(
child: Padding(
padding: const EdgeInsets.fromLTRB(15.0, 5.0, 15.0,5.0),
child: new Card( //listView(income),
child: Padding(
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0,0.0),
child: new Column(
children: <Widget>[
listView(income),
new ButtonBar(
children: <Widget>[
new RaisedButton.icon(
label: const Text('Edit'),
icon: Icon(Icons.edit,),
color: colorPrimary,
onPressed: () {
_navigateAndDisplaySelection(context, income);
/* Navigator.push(context,
MaterialPageRoute(builder: (context) => AddEditIncomeForm(incomeData: income)));*/
},
),
new RaisedButton.icon(
label: const Text('Delete'),
icon: Icon(Icons.delete),
color: colorPrimary,
onPressed: () {
//database.deleteEntry(income);
//deleteConfirmation(income, database);
showDialog(
context: context,
builder: (context) {
return CheckBoxAlertDialog(transactionType: delete, data: income, database: database,);
}
);
},
),
],
),
],
),
),
)
)
);
}).toList(),
);
}
this is the code for the content of the card view
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(common_functions(incomeList.dateReceived.toString()),
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold )),
Spacer(),
//Expanded(child: SizedBox()),
Text("Not Received"),
Switch(
value: isSwitched,
onChanged: (value) {
setState(() {
isSwitched = value;
print(isSwitched);
});
},
activeTrackColor: Colors.lightGreenAccent,
activeColor: Colors.green,
),
]
),
Row(
children: <Widget>[
CircleAvatar(
backgroundColor: green,
child: Icon(Icons.attach_money, color: white,),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(incomeList.category,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold )),
Text(incomeList.frequency + " | " + incomeList.depositAcct, style: TextStyle(color: grey, fontSize: 15)),
],
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text("\$" + incomeList.expectedAmount.toStringAsFixed(2),
style: TextStyle(fontSize: 18, color: green , fontWeight: FontWeight.bold ) ),
Text(incomeList.status, style: TextStyle(color: grey, fontSize: 15)),
],
),
],
),
],
);
if you take a look at the pic attached, the buttons and the top switch is not align properly to the number $68.00. see the red line i drawed. the switch on top is off to the left by a few spaces and also the buttons are the bottom are not align exactly to $68.00
am i doing something wrong that the widgets are not aligning to the red line as $68.00 is? how can i change my code to properly align all the widgets on the right side? thanks in advance
For ButtonBar it's buttonPadding parameter. Just be sure not to use any horizontal padding with it (right or left), since it will split it between the buttons. You will have to add a left padding for the buttons inside the ButtonBar.
I've attached an example for it and for the Switch widget, which doesn't have any properties to modify this behavior, but you can always use Transform.translate to overcome this.
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Transform.translate(
offset: Offset(10.0, 0.0),
child: Switch(
value: true,
onChanged: (value) {},
activeTrackColor: Colors.lightGreenAccent,
activeColor: Colors.green,
),
),
],
),
ButtonBar(
buttonPadding: EdgeInsets.zero,
children: <Widget>[
RaisedButton.icon(
label: const Text('Edit'),
icon: Icon(
Icons.edit,
),
color: Colors.blue,
onPressed: () {},
),
Padding(
padding: const EdgeInsets.only(left: 10.0),
child: RaisedButton.icon(
label: const Text('Delete'),
icon: Icon(Icons.delete),
color: Colors.blue,
onPressed: () {},
),
),
],
),

Place widgets correctly inside a Card

I'm trying to create a ListView with Card widget.
I have the ListView and the Card but I can't figure out how to place widgets correctly inside the Card itself. This is how it looks now:
I want the favorites icon and the image to keep their place, but to move the text to be near the image and to have the "Jean-Paul-Gaultier" text to be closer to the "Le Male" and have it align left.
This is what I have so far:
Widget _myListView(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index){
return Card(
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Image.network('${decoded[index]['image']}'),
),
],
),
SizedBox(width: 8,),
Column(
children: <Widget>[
Text(
'${decoded[index]['name']}',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
Row(
children: <Widget>[
Text(
'${decoded[index]['brand']}',
style: TextStyle(
color: Colors.blueGrey,
fontWeight: FontWeight.normal,
fontSize: 12,
),
),
],
),
],
),
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: Icon(Icons.favorite_border),
),
],
),
],
),
);
},
);
}
Without the mainAxisAlignment: MainAxisAlignment.space-between the text is indeed closer to the image, but the favorites icon gets right near the text which is something I do not want.
I tried to search for answers but as I'm new to Flutter I don't really know the right keywords so I couldn't find anything.
A much easier approach would be using a ListTile
Widget _myListView(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text("title"),
subtitle: Text("subtitle"),
leading: Container(
width: 48, height: 48,
child: Placeholder(), //place image here replacing the Placeholder widget
),
trailing: IconButton(
icon: Icon(Icons.favorite_border),
onPressed: () {},
),
),
);
},
);
}
which gives us
But if you want your code then here it is
Widget _myListView(BuildContext context) {
return ListView.builder(
itemBuilder: (context, index) {
return Card(
child: Row(
children: <Widget>[
Container(
margin: const EdgeInsets.all(8.0),
child: Placeholder(),
width: 48,
height: 48,
),
SizedBox(
width: 8,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'title',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
Text(
'subtitle',
style: TextStyle(
color: Colors.blueGrey,
fontWeight: FontWeight.normal,
fontSize: 12,
),
),
],
),
Spacer(),
IconButton(
icon: Icon(Icons.favorite_border),
onPressed: () {},
),
],
),
);
},
);
}
EDIT
to reduce the space between title and subtitle replace the title with following code
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("title",style: Theme.of(context).textTheme.body2,),
Text("subtitle",style: Theme.of(context).textTheme.caption,),
],
),