Related
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),
),
),
),
],
)
I just started flutter. I tried to make a card structure but I think it is quite wrong. I could never fix it. I am using Gridview extend. In this way, the column numbers change dynamically as the screen gets smaller or larger. but i keep getting overflow error what should i do.
var response = sepet.itemsCount[item.name];
return SizedBox(
child: Padding(
padding: EdgeInsets.all(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: InkWell(
customBorder: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
onTap: () {},
child: Column(
children: <Widget>[
ListTile(
title: Text(item.name ?? ''),
subtitle: Text(item.defaultPrice.toString() + '\$'),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
countChanger(sepet, false, item),
Padding(
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Text(
response != null ? response.toString() : '0',
style: TextStyle(fontSize: 18.0),
),
),
countChanger(sepet, true, item),
],
),
ButtonTheme(
height: 25,
minWidth: 25,
child: ElevatedButton(
onPressed: () {
!isAdded
? sepet.sepeteEkle(item)
: sepet.deleteItem(item);
},
style: ElevatedButton.styleFrom(
primary: !isAdded
? Colors.teal
: Colors.red,
),
child: Text(!isAdded ? 'Ekle' : 'Çıkar'),
),
),
],
),
)
],
),
),
),
],
),
),
);
My gridview extend structure is like this
child: GridView.extent(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
maxCrossAxisExtent: 250.0,
crossAxisSpacing: 20.0,
mainAxisSpacing: 20.0,
children: List.generate(foods!.length, (index) {
return itemCard(foods[index].menuItem ?? MenuItem(), value);
}),
The question you need to answer is what would you like to happen if the width of that card is so small? Do you want a different arrangement of those elements? If you do decide on what that would look like and check the constraint with LayoutBuilder Or the whole screen width with MediaQuery whatever you feel is best. You could also make that bit scroll horizontally by using SingleChildScrollView. This is a design decision. You must image what things look like when screen size changes, and be as deliberate as possible with the responsiveness rather then to just try to find some magic widget which we are all guilty of doing sometimes.
Try below code hope its helpful to you I have try similar to your code and add your widgets in Expanded or Flexible Widgets.
flexible widgets
expanded Widgets
GridView.builder(
padding: const EdgeInsets.all(8),
itemCount: 4,
itemBuilder: (ctx, i) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Text('data'),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
margin: EdgeInsets.all(10),
height: 35.0,
width: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: Colors.grey,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
InkWell(
child: Icon(Icons.remove, color: Colors.green),
onTap: () {},
),
Spacer(),
Text(
'0',
style: Theme.of(context)
.textTheme
.subtitle2!
.copyWith(fontSize: 16.0),
),
Spacer(),
InkWell(
child: Icon(
Icons.add,
color: Colors.green,
),
onTap: () {},
),
],
),
),
),
Expanded(
child: ElevatedButton(
onPressed: () {},
child: Text(
'Sub Total',
style: TextStyle(
fontSize: 15,
),
),
),
),
],
),
],
),
);
},
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 170.0,
mainAxisExtent: 93,
),
),
Your Result screen like->
i have three buttons in my login page each of them are a different type of login options when i type in bigger texts in one button that itself is changing how can i keep everything constant.can someone look into it please.
Here's my code:
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlutterLogo(size: 150),
SizedBox(height: 50),
_signInButton(),
_signInFbButton()
],
),
),
),
);
}
Widget _signInButton() {
return Container(
child: OutlineButton(
splashColor: Colors.grey,
onPressed: () {
signInWithGoogle().whenComplete(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return FirstScreen();
},
),
);
});
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: Colors.grey),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage("Assets/google_logo.png"), height: 35.0),
Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
'Sign in with Google',
style: TextStyle(
fontSize: 20,
color: Colors.grey,
}
Widget _signInFbButton() {
return Container(
child: OutlineButton(
splashColor: Colors.grey,
onPressed: () {
signInWithGoogle().whenComplete(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return FirstScreen();
},
),
);
});
},
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: Colors.grey),
child: Container(
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 10),
child: Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image(image: AssetImage("Assets/facebook-logo.png"), height: 35.0),
Padding(
padding: const EdgeInsets.only(left: 10),
child: Text(
'Sign in with Google',
style: TextStyle(
fontSize: 20,
color: Colors.grey,
here's the screen shot of how many buttons are arranged i want to have all the buttons constant and texts inside it formatted properly:
You don't need the column I think. So, I removed that. Here is the way you can create custom button with size. Feel free to change minWidth to get the best result.
new: Please consider using Flexible and Expanded inside the row. If the button text goes in multi-line please reduce the font size to fix it.
Widget _signInButton() {
return ButtonTheme(
minWidth: 400.0,
padding: EdgeInsets.all(10),
child: OutlineButton(
splashColor: Colors.grey,
onPressed: () {},
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
highlightElevation: 0,
borderSide: BorderSide(color: Colors.grey),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
flex: 1,
child: Image.network(
'https://picsum.photos/250?image=9',
height: 35,
),
),
Expanded(
flex: 1,
child: Padding(
padding: const EdgeInsets.only(left: 10),
child: Text('Sign in with Facebook',
style: TextStyle(
fontSize: 20, color: Colors.grey))),
)
])
),
);
}
I've been trying to make my button to fill my container.
But as you can see from the picture above, the button (red) on the left clearly did not fill the entire container(green). I can solve this by adding height to MaterialButton, but IMHO this is not the best solution, because device's height might differ. Can you help me to solve this problem? Thanks.
Here is my code:
Row(
children: <Widget>[
Expanded(
child: Container(
color: Colors.green,
child: MaterialButton(
color: Colors.red,
child: Text("Button A"),
onPressed: () {},
),
),
),
Expanded(
child: MaterialButton(
color: Colors.blue,
child: Text("Button B"),
onPressed: () {},
),
),
],
),
Simply Add - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, in MaterialButton
Row(
children: <Widget>[
Expanded(
child: Container(
color: Colors.green,
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, // Add this
color: Colors.red,
child: Text("Button A"),
onPressed: () {},
),
),
),
Expanded(
child: MaterialButton(
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, // Add this
color: Colors.blue,
child: Text("Button B"),
onPressed: () {},
),
),
],
),
You may can try
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Container(
color: Colors.green,
child: SizedBox(
height: 48,
child: MaterialButton(
height: double.infinity,
color: Colors.red,
child: Text("Button A"),
onPressed: () {},
padding: EdgeInsets.all(0),
),
),
),
),
Expanded(
child: SizedBox(
height: 48,
child: MaterialButton(
height: double.infinity,
color: Colors.blue,
child: Text("Button B"),
onPressed: () {},
),
),
),
],
),
the Row in my container contains padding on the left(I think). I want to align with the other children in the Column. I've been playing around with padding for the last two hours and find out how to eliminate the padding...
The sign in should align vertically from the left with buttons above it
#override
Widget build(BuildContext context) {
return SafeArea(
child: Container(
height: MediaQuery.of(context).size.height,
child: Stack(
alignment: Alignment.topCenter,
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/img/signin.png'),
fit: BoxFit.cover,
),
),
),
Container(
padding: EdgeInsets.only(top: 100),
child: Opacity(
opacity: _showProgressIndicator ? 1 : 0,
child: CircularProgressIndicator(),
),
),
Container(
// height: MediaQuery.of(context).size.height - 180,
padding:
EdgeInsets.only(top: 20, left: 10, right: 10, bottom: 60),
child: Form(
key: formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
verticalDirection: VerticalDirection.up,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
new FlatButton(
padding: EdgeInsets.zero,
child: new Text('SIGN IN',
style: Theme.of(context).textTheme.body1),
onPressed: () {
Navigator.push(
context, SignInPage(widget.onSignedIn));
},
),
Opacity(
opacity: _showMessage ? 1 : 0,
child: Text('CONSIDER GOOGLE', style:Theme.of(context).textTheme.body1)),
new FlatButton(
padding: new EdgeInsets.all(0.0),
child: new Text(
'SIGN UP WITH EMAIL',
style: Theme.of(context).textTheme.body1,
),
onPressed: () {
Navigator.push(
context, SignUpPage(widget.onSignedIn));
},
),
]),
new Container(
// padding: EdgeInsets.all(10),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new RaisedButton(
color: Colors.blue[800],
padding: EdgeInsets.all(20),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(4))),
child: new Text('CONNECT WITH FACEBOOK',
style: new TextStyle(
fontSize: 16,
letterSpacing: 0.5,
color: Colors.white)),
onPressed: loginWithFb,
),
new SizedBox(height: 20),
new RaisedButton(
color: Colors.red,
padding: EdgeInsets.all(20),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(4))),
child: new Text('CONNECT WITH GOOGLE',
style: new TextStyle(
fontSize: 16,
letterSpacing: 0.5,
color: Colors.white)),
onPressed: loginWithGoogle,
),
],
),
),
],
),
))
],
),
),
);
}
I could fix this by changing the default ButtonTheme if I understand correctly what you mean, because you said:
The sign in should align vertically from the left with buttons above it
Don't you mean horizontally from the left, if that is the case try this:
Wrap the Flatbutton in a Theme with ThemeData and a new ButtonTheme, then change the padding and minWidth with your own(when I only changed the padding or width it didn't work).
This removes the default from the ButtonTheme
Example:
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Theme(
data: ThemeData(buttonTheme: ButtonThemeData(minWidth: 20.0,padding: EdgeInsets.all(0.0))),
child: new FlatButton(
child: new Text('SIGN IN',
style: Theme.of(context).textTheme.body1),
onPressed: () {
},
),
),
Opacity(
opacity: true ? 1 : 0,
child: Text('CONSIDER GOOGLE', style:Theme.of(context).textTheme.body1)),
new FlatButton(
padding: new EdgeInsets.all(0.0),
child: new Text(
"SIGN UP WITH EMAIL ",
style: Theme.of(context).textTheme.body1,
),
onPressed: () {
},
),
]),
Result: