Centered Text inside a button with an icon in Flutter - flutter

I'm having issues where I want to make a button (any kind to achieve this) that has an icon that is always in the same position at the start of the button, and that the text of the button is always centered compared to the text below it and always centered in the button itself, even if the text is dynamic. This is what I want to achieve:
The button text is centered according to the text below(that stays the same) and it is centered with the above button, but if the button text changes dynamically, then I have these issues:
Or like this one:
Any ideas how to solve this problem?
I tried with the Expanded widget and adding the flex properties but failed. I tried some other stuff too but failed also... Here is the button code:
TextButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.blue)),
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: Icon(
Icons.keyboard_arrow_right_sharp,
color: Colors.white,
),
),
Expanded(
flex: 4,
child: Center(
child: Text(
"SOME TEXT",
style: TextStyle(color: Colors.white),
),
),
)
],
),
),
Thanks in advance for your help!

There are a couple of options to do that. I'm going to assume the size of the text could change so you want a flexible solution.
The first option is the most obvious of the two, but will break if the text is too long. The trick is to add an empty sizedBox at the end of the button, so the text can be centered in an expanded widget.
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue),
),
onPressed: () {},
child: Row(
children: [
Icon(
Icons.keyboard_arrow_right_sharp,
color: Colors.white,
size: 24,
),
Expanded(
child: Center(
child: Text(
"SOME TEXT",
style: TextStyle(
color:Colors.white,
),
),
),
),
SizedBox(
width: 24, // width of the icon
),
],
),
);
The other option is using a stack widget. This way, if the text is too long it will overlap with the icon but it's less probable that it will overflow the button.
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue),
),
onPressed: () {},
child: Stack(
children: [
Positioned(
left: 0,
child: Icon(
Icons.keyboard_arrow_right_sharp,
color: Colors.white,
size: 24,
),
),
Center(
child: Text(
"SOME TEXT",
style: TextStyle(
color:Colors.white,
),
),
),
],
),
);

Let's discuss about you code :
using row with a mainaxisalignment from start make the element start from the available area. then i suggest to use the SizedBox to make some of spacing between the elements as you want and play with the width of it.
TextButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.blue)),
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.start, // here the issue
children: [
Expanded(
flex: 1,
child: Icon(
Icons.keyboard_arrow_right_sharp,
color: Colors.white,
),
),
SizedBox(width: MediaQuery.of(context).size.width * 0.08, // change this value as you want 0.08 or 0.1 ...etc
),
Expanded(
flex: 4,
child: Center(
child: Text(
"SOME TEXT",
style: TextStyle(color: Colors.white),
),
),
)
],
),
),
for more read this documentation

Related

How can I fix this "right Overflowed by 39 Pixels error" in the middle of a row?

I tried alining two rows within a SizedBox-widget and it doesn't look like that there should be an overflow right now, but there is one.
This is the code, and the picture of how it looks like right now is down below.
SizedBox(
height: MediaQuery.of(context).size.height * 0.1,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//Profile
Expanded(
child: Row(
children: [
OutlinedButton(
onPressed: () => {Navigator.push(context,
MaterialPageRoute(builder: (_) => const Profile()))
},
style: OutlinedButton.styleFrom(
shape: const CircleBorder(),
padding: const EdgeInsets.all(2)
),
child: CircleAvatar(
backgroundColor: primary,
backgroundImage: NetworkImage(profilePath),
radius: 24,
)
),
//rowSpacer,
Text(profileName, style: categoryNF),
],),
),
// Likes
Expanded(
child: Row (
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
onPressed: () => {},
icon: const Icon(
Icons.favorite_border,
size: 32,
color: Colors.redAccent,
),
),
//rowSpacer,
Text("$likes Likes", style: categoryNF),
],)
),
],
),
),
Try wrap your name Text with Expanded widget like this:
Expanded(child: Text(profileName, style: categoryNF),),
use this Text(profileName,overflow: TextOverflow.ellipsis, style: categoryNF) for more refer this answer
I'm not entirely sure what you're asking, but it sounds like you want to know how to fix the "right Overflowed by 39 Pixels" error in your code.
The easiest way to fix this is to simply add a padding to the right side of your row. For example:
Row(
padding: EdgeInsets.only(right: 16.0), // add this
children: [
// your widgets here
],
),
This will add 16 pixels of padding to the right side of your row, which should be enough to fix the overflow error.

Dont know how to lock the center of a widget and separate it from the others

I'm creating an app with the main menu and different minigames, I'm starting with Flutter, so I don't understand properly how to manage the widgets properly, in this case, I have simplified the code because what I want is to understand the hierarchy, and how to place the widgets properly
child: Scaffold(
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Flexible(
flex: 1,
child: Container(
child: Text(_element, style: new TextStyle( fontSize: 28.0, color: Colors.black), textAlign: TextAlign.center,
),
),
),
Flexible(
flex: 1,
child: Container(
child: ElevatedButton(
child: Text('Next', style: new TextStyle( fontSize: 100.0, color: Colors.black)),
onPressed: () {
getNextElement();
},
),
),
),
],
),
),
)
With this code I get this:
What I have
I want to understand how to use widgets properly and in which order.
And my problem is that I want the button at the bottom and the text in the center, and when I press the button the text changes so when it is a longer phrase the size of the text container changes and it expands to the top of it but without changing the width, but I want it to be centered and when the text is bigger I want it to expand up and down like this:
Objective:

arranging a scaffold with buttons

i wrote this code in flutter and i wanna know if i can make it better,
i did a lot of "work around" that i feel there's a better way to write it.
especially the buttons with the expanded between them, and the sizedbox.
the screen has text in the middle(getVerse), and and two buttons, one is bottom left and the other is bottom right.
the first expanded separate the text from the buttons, and the second expanded is to separate the two buttons
help is appreciated and thanks for your time.
Scaffold(
appBar: AppBar(
title: Text(
suras.elementAt(widget.index),
textAlign: TextAlign.right,
),
),
body: Column(
children: [
SizedBox(
height: 100,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
getVerse(widget.index + 1, currentVerse),
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 24,
fontFamily: 'KFGQPC BAZZI Uthmanic Script',
),
),
),
Expanded(child: Container()),
Row(
children: [
ElevatedButton(
onPressed: () {
setState(() {
currentVerse++;
});
},
child: Text('not sure'),
),
Expanded(child: Container()),
ElevatedButton(
onPressed: null,
child: Text('sure'),
),
],
),
],
),
);
If you want that those 2 buttons to stay at the bottom you can use floatingActionButton in the Scaffold property. You can change the location of those buttons with the floatingActionButtonLocation.
Scaffold(
appBar: AppBar(
title: Text('MyApp'),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
onPressed: () {},
child: Text('Not sure'),
),
ElevatedButton(
onPressed: () {},
child: Text('Sure'),
)
],
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'My Text',
textAlign: TextAlign.center,
),
),
),

How to center AlertDialog FlatButton in Flutter

How can I style the FlatButton to be aligned on center without having to create a custom AlertDialog?
AlertDialog(
title: Text(
'Alert Dialog'.toUpperCase(),
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 28.0),
),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('Scrollable AlertDialog' * 100),
],
),
),
actions: <Widget>[
FlatButton(
child: Text(
'Accept'.toUpperCase(),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
This is how it looks like
I tried removing 'actions' and adding the FlatButton inside a row in 'content', but the scroll stopped working and the content overflowed.
content: Column(
children: <Widget>[
SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('Scrollable AlertDialog.' * 50),
],
),
),
Row(
children: <Widget>[
FlatButton(
child: Text(
'Accept'.toUpperCase(),
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 16.0
),
),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
],
),
Google's material design guidelines don't want you to place that in center, which is why Flutter team used ButtonBar for actions and you have no control over ButtonBar's alignment inside actions property, so if you really want to center your single button, there are 2 simple workarounds:
Make changes in source code, in dialog.dart's AlertDialog's build method, you'll see a ButtonBar, widget, add alignment to it.
ButtonBar(
alignment: MainAxisAlignment.center, // add this line
// ...
)
You can use dummy widgets like SizedBox and provide some width to it.
actions: [
SizedBox(width: space),
FlatButton(
onPressed: () {},
child: Text('Button'),
),
SizedBox(width: space),
]
Screenshot:
Try to play around with actionsPadding which is one of the property of AlertDialog.
final horizontalPadding=50;
horizontal padding is the one that is transparent to the left and right of the dialog.
actionsPadding: EdgeInsets.only(right: MediaQuery.of(context).size.width/2-horizontalPadding*2),
Also, go through How to style AlertDialog Actions in Flutter . You can change and play around within the library as mentioned here. But, this may not work for your colleagues who are sharing the git repo. They will have to update their libraries as well in their local machines.
actions: <Widget>[
Align(
alignment: Alignment.center,
child: ElevatedButton(
onPressed: () {
//your logic
Navigator.pop(context);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Close'),
),
),
),
],
Just use actionsAlignment property in AlertDialog Widget.
AlertDialog(
actions: ...,
actionsAlignment: MainAxisAlignment.spaceBetween
)

how to add icon at right side of RaisedButton?

How to add icon to RaisedButton at the right side
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: new SizedBox(
width: double.infinity,
child: new RaisedButton(
textColor: Colors.white,
color: coloraccent,
onPressed: () {},
child: const Text('UPADATE'),
)),
),
You can just wrap your RaisedButton.icon to the Directionality widget:
Directionality(
textDirection: TextDirection.rtl,
child: RaisedButton.icon(
onPressed: () {},
color: Colors.deepPurple,
icon: Icon(
Icons.arrow_drop_down,
color: Colors.white,
),
label: Text(
"Category",
style: TextStyle(color: Colors.white),
),
),
)
You can try this out, it works fine for me.
child: RaisedButton(
onPressed: () => navigateToLogin(context),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Continue",style: TextStyle(fontSize: 20)),
Icon(Icons.navigate_next)
],
),
use RaisedButton.icon constructor
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: SizedBox(
width: double.infinity,
child: RaisedButton.icon(
icon: Icon(Icons.translate),
textColor: Colors.white,
color: Colors.lightBlue,
label: const Text('UPADATE'),
onPressed: () {},
)),
),
give a child to raised button like that
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween
children: <Widget>[
Text('some text'),
Icon(Icons.home),
],
),
I tried to use RaisedButton.Icon but it was not enough for me, because I usually customize the buttons with many design styles, so I used some techniques for placing text and Icon with RaisedButton.
You can try this, It worked for me. Let me explain in the code.
// Create a Raised Button.
RaisedButton(
color: Colors.pinkAccent, // Color pinkAccent
child: Row( // Add a Row Widget for placing objects.
mainAxisAlignment: MainAxisAlignment.center, // Center the Widgets.
mainAxisSize: MainAxisSize.max, // Use all of width in RaisedButton.
children: <Widget>[
Padding(
padding: EdgeInsets.all(5.0), // Give to the text some space.
child: Text(
"Enviar",
style: TextStyle(
fontSize: 18, // 18pt in font.
color: Colors.white, // You can ommit it if you use textColor in RaisedButton.
),
),
),
Icon(
Icons.send, // Send Icon. (Papper Plane Icon)
color: Colors.white, // White Color. You can ommit it too if you use textColor property on RaisedButton.
size: 18, // 18 pt, same as text.
),
],
),
onPressed: () {}, /// For enabling the button
),
Use RaisedButton.icon:
Doc says: Create a filled button from a pair of widgets that serve as
the button's icon and label.
The icon and label are arranged in a row and padded by 12 logical
pixels at the start, and 16 at the end, with an 8 pixel gap in
between.
RaisedButton.icon(
icon: Icon(Icons. ...), // <-- Icon you want.
textColor: Colors.white,
color: Colors.lightBlue,
label: const Text('UPADATE'), // <-- Your text.
onPressed: () {},
)),
use this code. you can add your required width as per text length
Container(
height: 35.0,
width: 95,
child: RaisedButton(
elevation: 10,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0),
),
),
color: Colors.white,
child: Row(
children: <Widget>[
Text('Call', style: TextStyle(color: Colors.black)),
SizedBox(width: 10),
Icon(Icons.call),
],
),
onPressed: () {},
),
);
If you still resist using RaisedButton.Icon instead of using the normal RaisedButton with Row widget as a child
Then you can swap between label and icon attributes because they both take a widget.
Like this:
RaisedButton.icon(
icon: const Text('UPADATE'),
label: Icon(Icons.translate),
textColor: Colors.white,
color: Colors.lightBlue,
onPressed: () {},
)
Here is my two buttons, Back and Next
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
color: const Color(0xFFFFB822), // Color pinkAccent
child: Row(
// Add a Row Widget for placing objects.
mainAxisAlignment: MainAxisAlignment.center, // Center the Widgets.
mainAxisSize: MainAxisSize.max, // Use all of width in RaisedButton.
children: <Widget>[
SizedBox(height: 10, width: 10),
Icon(
Icons.arrow_back_ios, // Send Icon. (Papper Plane Icon)
color: Colors.black, // White Color. You can ommit it too if you use textColor property on RaisedButton.
size: 18, // 18 pt, same as text.
),
Padding(
padding: EdgeInsets.all(5.0), // Give to the text some space.
child: Text(
"Back",
style: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.black, // You can ommit it if you use textColor in RaisedButton.
),
),
),
],
),
onPressed: () {},
/// For enabling the button
),
RaisedButton(
color: const Color(0xFFFFB822), // Color pinkAccent
child: Row(
// Add a Row Widget for placing objects.
mainAxisAlignment: MainAxisAlignment.center, // Center the Widgets.
mainAxisSize: MainAxisSize.max, // Use all of width in RaisedButton.
children: <Widget>[
Padding(
padding: EdgeInsets.all(5.0), // Give to the text some space.
child: Text(
"Next",
style: TextStyle(
fontWeight: FontWeight.w900,
color: Colors.black, // You can ommit it if you use textColor in RaisedButton.
),
),
),
Icon(
Icons.arrow_forward_ios, // Send Icon. (Papper Plane Icon)
color: Colors.black, // White Color. You can ommit it too if you use textColor property on RaisedButton.
size: 18, // 18 pt, same as text.
),
],
),
onPressed: () {},
/// For enabling the button
),
],
),