Flutter How to align row widget children to left and center - flutter

I am trying to create social login buttons like below image. I want to align textbutton icon and name to left. also center the row they are in so that the icon and text align vertically when using multiple text buttons.
expected result:
My Result:
My Code for button:
TextButton(
onPressed: onTap,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
alignment: Alignment.centerLeft,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
width: 30,
child: Image.asset(
icon,
fit: BoxFit.cover,
),
),
),
Align(
alignment: Alignment.centerLeft,
child: Text(
buttonName,
style: kBodyText2,
textAlign: TextAlign.left,
),
),
],
),
style: TextButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(SizeConfig.blockSizeH! * 3),
),
),
),

You should use ListTile()
instead.
Set title: "Continue with Google".
And leading: you can set the logo.
The positions will always stay the same no matter how long your title will be, you also have extra options like subtitles and trailing actions.
To make it act like a button use
onTap: (){}

You can achieve that by using the Expanded widget: Like so:
Padding(
padding: const EdgeInsets.all(8.0),
child: TextButton(
onPressed: (){},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Container(),),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.centerLeft,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
width: 30,
child: Icon(Icons.access_alarm),
),
),
),
Expanded(
flex: 5,
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'test text test',
textAlign: TextAlign.left,
),
),
),
],
),
style: TextButton.styleFrom(
backgroundColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
),
const SizedBox(height: 30),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextButton(
onPressed: (){},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(flex: 1, child: Container(),),
Expanded(
flex: 2,
child: Align(
alignment: Alignment.centerLeft,
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
width: 30,
child: Icon(Icons.access_alarm),
),
),
),
Expanded(
flex: 5,
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'test text test test',
textAlign: TextAlign.left,
),
),
),
],
),
style: TextButton.styleFrom(
backgroundColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
),

You can exploit the fact the these icons are the same size, to easily align them. Each of your TextButton already holds a Row, but instead of fancy layout stuff, you can just insert padding to the Icon by adding blank spaces using SizedBox, like so:
TextButton(
child: Row(
children: [
const SizedBox(width: 16), // padding in the beginning
Icon(Icons.download), // the icon, or image, or whatever
const SizedBox(width: 16), // padding in-between
Text('Button ' * i), // the text
],
),
onPressed: () {},
)
Result:
Code used to produce the above demo:
Column(
mainAxisSize: MainAxisSize.min,
children: [
for (int i = 1; i < 6; i++)
TextButton(
child: Row(
children: [
const SizedBox(width: 16),
Icon(Icons.download),
const SizedBox(width: 16),
Text('Button ' * i),
],
),
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
),
],
)

Related

How to get a button to align to the bottom of a column in the row

I'm trying to align a Text button to the bottom of a column in a row but everything I'm trying is keeping it aligned to the top of the column.
I have a Container Child → ROW with 3 sections Image, SizedBox, (Column→ Button.)
I want to align the button to the bottom right.
The alignment properties in the Column doesn't appear to have any effect and are staying with the ROW alignment.
I have tried Align also and still nothing moves
CrossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
Here is my code:
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft: Radius.circular(10.0)),
child: Image.network(
constants.baseImages + snapshot.data[index].logo,
width: 80,
height: 80,
fit: BoxFit.cover,
),
),
SizedBox(
width: 215,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(snapshot.data[index].restaurantName),
Padding(
padding: const EdgeInsets.only(
top: 2.0, bottom: 2.0),
child: Text(
snapshot.data[index].address,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
maxLines: 2,
),
),
],
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Align(
alignment: Alignment.bottomLeft,
child: TextButton(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all<Color>(
Colors.blue),
),
onPressed: () {},
child: Text('More Info'),
),
),
],
),
]),
);
Can someone explain where I am going wrong
Thanks
On your last Column use MainAxisAlignment.end, Also you can include Spacer widget and rebuild the app.
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
// Spacer(), //
TextButton(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all<Color>(Colors.blue),
),
onPressed: () {
print("more infor ");
},
child: Text('More Info'),
),
],
Column isn't required, try
Align(
alignment: Alignment.bottomLeft,
child: TextButton(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all<Color>(
Colors.blue),
),
onPressed: () {},
child: Text('More Info'),
),
),

ScrollView RenderFlex overflow - Flutter

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),
),
),
),
),
),
),
],
),
),
),

How to align Icon with most top Text

Consider this UI:
Code:
Widget shopHeader(var shopName, var shopAddress){
return Container(
height: 200,
margin: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.all(1.0),
child: const Icon(Icons.home, color: Colors.black),
decoration: const BoxDecoration(
color: Colors.grey, // border color
shape: BoxShape.circle,
),
),
const SizedBox(
width: 10,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
shopName,
style: TextStyle(fontSize: 17),
),
Text(
shopAddress,
style: TextStyle(fontSize: 14, color:Colors.black38),
),
Padding(
padding: EdgeInsets.only(left:0.0, right:0.0, top:20.0, bottom:0.0),
child: SizedBox(
width: 150,
child: ElevatedButton(
child: Text('Chat'),
onPressed: () {},
))
)
],
),
],
),
);
}
The icon on the left is too low. How to set it so it's align with "Awesome Shop" text?
On the topmost Row widget use the crossAxisAllignment property to CrossAxisAllignment.start.

How do I add a splash effect on a card using GestureDetector

I wan't to add splash effect over the card when tapped on it.
I referred some of the answers on stackoverflow but, nothing caught up in my brai. HELP!!
My Code -
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
Container(
height: 100,
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/page1');
},
child: GradientCard(
gradient: LinearGradient(
colors: [Colors.yellow, Colors.lightGreenAccent]),
elevation: 10,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
child: Center(
child: Row(
children: <Widget>[
SizedBox(width: 25),
Icon(
Icons.favorite,
color: Colors.redAccent,
size: 50,
),
SizedBox(width: 40),
Text(
"MY CARD",
style: TextStyle(fontSize: 28),
),
],
),
),
),
),
),
),
],
),
),
I also tried to wrap onTap: function with InkWell with an ancestor as Material, But it won't let me to do so. Actually, I am confused now and stucked. Any help will be apperiated!!
Try this and let me know if that works!
Container(
padding: EdgeInsets.all(10),
child: ListView(
children: <Widget>[
Container(
height: 100,
child: GradientCard(
gradient: LinearGradient(
colors: [Colors.yellow, Colors.lightGreenAccent]
),
elevation: 10,
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.pushNamed(context, '/page1');
},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
child: Center(
child: Row(
children: <Widget>[
SizedBox(width: 25),
Icon(
Icons.favorite,
color: Colors.redAccent,
size: 50,
),
SizedBox(width: 40),
Text(
"MY CARD",
style: TextStyle(fontSize: 28),
),
],
),
),
),
)
)
)
),
],
),
);
Try this:
Container(
height: 100,
child: Material(
elevation: 10,
color: Theme.of(context).cardColor,
child: InkWell(
onTap: () {
Navigator.pushNamed(context, '/page1');
},
child: Center(
child: Row(
children: <Widget>[
SizedBox(width: 25),
Icon(
Icons.favorite,
color: Colors.redAccent,
size: 50,
),
SizedBox(width: 40),
Text(
"MY CARD",
style: TextStyle(fontSize: 28),
),
],
),
),
),
),
)

Flutter - Push FlatButton at near bottom

I want to push the flatbutton.icon near bottom but not in bottomNavigationBar.
I want also to make it dynamic so that i can add more buttons vertically if needed.
I'm thinking of using Stack then positioned but i'm not familiar on how to implement it.
return MaterialApp(
home: Scaffold(
backgroundColor: Theme.of(context).accentColor,
body: Center(
child: Column(
children: <Widget>[
AvatarGlow(
endRadius: 90,
duration: Duration(seconds: 2),
glowColor: Colors.white24,
repeat: true,
repeatPauseDuration: Duration(seconds: 2),
startDelay: Duration(seconds: 1),
child: Material(
elevation: 8.0,
shape: CircleBorder(),
child: CircleAvatar(
backgroundColor: Colors.grey[100],
child: FlutterLogo(
size: 50.0,
),
radius: 50.0,
)),
),
DelayedAimation(
child: Text(
"PICKNIC",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 35.0,
color: Colors.white),
),
delay: delayedAmount + 1000,
),FlatButton.icon(
onPressed: () {
Navigator.of(context).pushNamed('/Pages', arguments: 2);
},
padding: EdgeInsets.symmetric(vertical: 14),
color: Theme.of(context).primaryColorDark.withOpacity(0.1),
icon: new Icon(MdiIcons.facebook, color: Theme.of(context).primaryColorDark),
shape: StadiumBorder(),
label: Text(
'Login with Facebook',
textAlign: TextAlign.start,
style: TextStyle(
color: Theme.of(context).primaryColorDark,
),
),
),
],
),
),
),
);
You will solve using Expanded widget.
Expanded(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: MaterialButton(
onPressed: () => {},
child: Text(_register ? 'REGISTER' : 'LOGIN'),
),
),
),
You can check following solutions:
If you need 1 button, simply use FloatingActionButton docs
If you need multiple suggest this article (Column with FABs)
And animated solution looks more user friendly package
If you want to have the content centered in the available space above the buttons, you could put your content centered in a Expanded widget and put the buttons below it, like this:
Center(
child: Column(
children: <Widget>[
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AvatarGlow(...),
DelayedAimation(...),
],
),
),
FlatButton.icon(...),
FlatButton.icon(...),
],
),
)
If you want to have the content centered in the entire screen and the buttons at the bottom, you could use a Stack, like this:
Stack(
children: <Widget>[
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AvatarGlow(...),
DelayedAimation(...),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
FlatButton.icon(...),
FlatButton.icon(...),
],
),
)
],
)