Below is a part of the code that displays the buttons below the body.
......
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () {},
child: Text("One button"),
),
),
SizedBox(
//space between button
width: 5,
),
Expanded(
child: OutlinedButton(
onPressed: () {},
child: Text("Two button"),
),
),
],
),
)
......
But the problem is that the width of the buttons is obtained for the entire page. And I would like it to be limited to the width of the body BoxConstraints(maxWidth: 800).
In the photo, I marked the desired width of the buttons with red borders.
How can I achieve this.
You wrap full button widget with ConstrainedBox.
ConstrainedBox(
constraints: BoxConstraints(maxWidth: 800),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () {},
child: Text("One button"),
),
),
SizedBox(
//space between button
width: 5,
),
Expanded(
child: OutlinedButton(
onPressed: () {},
child: Text("Two button"),
),
),
],
),
),
)
If you like to avoid padding, you can remove it or use ConstrainedBox on Row.
You could add 2 Expanded Widgets and use the flex property. Expanded, flex
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Expanded(
flex: 10,
child: Container(),
),
Expanded(
flex: 40,
child: OutlinedButton(
onPressed: () {},
child: Text("One button"),
),
),
SizedBox(
//space between button
width: 5,
),
Expanded(
flex: 40,
child: OutlinedButton(
onPressed: () {},
child: Text("Two button"),
),
),
Expanded(
flex: 10,
child: Container(),
),
],
),
)
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),
),
),
),
],
)
Problem: As you can see from the pic at the bottom, there is some extra white space above the grid layout that I don't want. I tried adjusting the alignment inside the container to centerTop but that didn't change anything. I think the problem has to do with Container and Gridview being inside an Expanded widget. Not sure how to go about removing that white space. That orange is from a scroll down event in order to show where the white space is. Any help would be much appreciated! Thank you.
Code:
class MyFavorites extends StatefulWidget {
MyFavorites();
_MyFavorites createState() => _MyFavorites();
}
class _MyFavorites extends State<MyFavorites> {
final FavController fC = Get.put(FavController());
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: colorPalette.chooseColor('offWhite'),
body: Column(
children: [
Spacer(flex: 1),
Expanded(
flex: 2,
child: Row(
children: [
Container(
alignment: Alignment.centerLeft,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.chevron_left),
color: colorPalette.chooseColor('darkGrey'),
),
),
Container(
margin: EdgeInsets.only(left: 23),
alignment: Alignment.centerLeft,
child: Text(
'My Favorites',
style: GoogleFonts.ubuntuCondensed(
color: colorPalette.chooseColor('darkGrey'),
fontSize: 32,
fontWeight: FontWeight.bold),
),
),
],
),
),
Expanded(
flex: 12,
child: Container(
child: GridView.count(
crossAxisCount: 2,
children: List.generate(fC.favItemNamesList.length, (index) {
return Container(
child: Card(
child: Column(
children: [
Expanded(
flex: 3,
child: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/empty_image.jpg',
fit: BoxFit.fill,
),
],
),
),
Expanded(
flex: 1,
child: Container(
color: colorPalette.chooseColor('offWhite'),
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
child: IconButton(
icon: Icon(
Icons.add,
color: colorPalette
.chooseColor('purple'),
),
onPressed: () {},
)),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
child: IconButton(
icon: Icon(
Icons.edit,
color: colorPalette
.chooseColor('green'),
),
onPressed: () {},
)),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
child: IconButton(
icon: Icon(
Icons.favorite,
color: Colors.pink,
),
onPressed: () {},
)),
),
],
),
),
),
Expanded(
flex: 1,
child: Container(
color: colorPalette.chooseColor('darkGrey'),
padding: EdgeInsets.only(left: 8),
alignment: Alignment.centerLeft,
child: Obx(
() => Text(fC.favItemNamesList[index],
style: GoogleFonts.ubuntuCondensed(
color: colorPalette
.chooseColor('offWhite'),
fontSize: 13)),
),
),
),
],
),
),
);
}),
),
),
),
],
),
);
}
}
Pic of problem:
Just do it as follows:
remove the first spacer, there is no need for it unless you need the above space. However you can use SafeArea Widget to avoid all the unseen places from the screen automatically if that is what you want.
Remove that container wrapping the grid view
your code should look like:
class MyFavorites extends StatefulWidget {
MyFavorites();
_MyFavorites createState() => _MyFavorites();
}
class _MyFavorites extends State<MyFavorites> {
final FavController fC = Get.put(FavController());
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: colorPalette.chooseColor('offWhite'),
body: Column(
children: [
Expanded(
flex: 2,
child: Row(
children: [
Container(
alignment: Alignment.centerLeft,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.chevron_left),
color: colorPalette.chooseColor('darkGrey'),
),
),
Container(
margin: EdgeInsets.only(left: 23),
alignment: Alignment.centerLeft,
child: Text(
'My Favorites',
style: GoogleFonts.ubuntuCondensed(
color: colorPalette.chooseColor('darkGrey'),
fontSize: 32,
fontWeight: FontWeight.bold),
),
),
],
),
),
Expanded(
flex: 12,
child: GridView.count(
crossAxisCount: 2,
children: List.generate(fC.favItemNamesList.length, (index) {
return Container(
child: Card(
child: Column(
children: [
Expanded(
flex: 3,
child: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/empty_image.jpg',
fit: BoxFit.fill,
),
],
),
),
Expanded(
flex: 1,
child: Container(
color: colorPalette.chooseColor('offWhite'),
child: Row(
children: [
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
child: IconButton(
icon: Icon(
Icons.add,
color: colorPalette
.chooseColor('purple'),
),
onPressed: () {},
)),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
child: IconButton(
icon: Icon(
Icons.edit,
color: colorPalette
.chooseColor('green'),
),
onPressed: () {},
)),
),
Expanded(
flex: 1,
child: Container(
alignment: Alignment.center,
child: IconButton(
icon: Icon(
Icons.favorite,
color: Colors.pink,
),
onPressed: () {},
)),
),
],
),
),
),
Expanded(
flex: 1,
child: Container(
color: colorPalette.chooseColor('darkGrey'),
padding: EdgeInsets.only(left: 8),
alignment: Alignment.centerLeft,
child: Obx(
() => Text(fC.favItemNamesList[index],
style: GoogleFonts.ubuntuCondensed(
color: colorPalette
.chooseColor('offWhite'),
fontSize: 13)),
),
),
),
],
),
),
);
}),
),
),
],
),
);
}
}
I am wondering why is it that my GridView is not rendering the widgets. I am trying to render the buttons in two columns and 2-3 rows.
The code is the following:
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
GridView.count(
shrinkWrap: true,
primary: true,
crossAxisCount: 2,
children: <Widget>[
Center(
child: FlatButton(
onPressed: () => {},
padding: EdgeInsets.all(10.0),
child: Column(children: <Widget>[
Image.asset(
'assets/img/wifi.png',
height: 50.0,
width: 50.0,
),
Text('Wifi')
]),
),
),
Center(
child: FlatButton(
onPressed: () => {},
padding: EdgeInsets.all(10.0),
child: Column(children: <Widget>[
Image.asset(
'assets/img/wifi.png',
height: 50.0,
width: 50.0,
),
Text('Key/Access')
]),
),
),
Center(
child: FlatButton(
onPressed: () => {},
padding: EdgeInsets.all(10.0),
child: Column(children: <Widget>[
Image.asset(
'assets/img/wifi.png',
height: 50.0,
width: 50.0,
),
Text('Key/Access')
]),
),
),
Center(
child: FlatButton(
onPressed: () => {},
padding: EdgeInsets.all(10.0),
child: Column(children: <Widget>[
Image.asset(
'assets/img/wifi.png',
height: 50.0,
width: 50.0,
),
Text('Key/Access')
]),
),
),
],
)
],
)));
}
}
I get an error, in the android emulator it renders yellow and black strips instead of the buttons with the corresponding images.
Wrap it with Container ( height: .. , width : double.infinity )
Or with SizedBox
Try removing the Column widget above the GridView
I have design like this
I tried adding 2 rows in the column and I got an error. that is, it exceeds the screen or the chart may not be rendered
this is my code
body: RefreshIndicator(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: GestureDetector(
child: Container(
margin: EdgeInsets.only(bottom: 320),
child: chart,
),
onTap: (){
_showDialog();
},
),
),
Expanded(
child: Column(
children: <Widget>[
RaisedButton(
padding: const EdgeInsets.symmetric(vertical: 50, horizontal: 65),
textColor: Colors.white,
color: Colors.blue,
onPressed: (){},
child: new Text("LAPOR"),
),
RaisedButton(
padding: const EdgeInsets.symmetric(vertical: 50, horizontal: 36),
textColor: Colors.white,
color: Colors.redAccent,
onPressed: (){},
child: new Text("PENGUMPULAN"),
),
],
),
),
],
),
onRefresh: _showDialog
)
Try wrapping your widgets in a SafeArea class
https://api.flutter.dev/flutter/widgets/SafeArea-class.html
https://www.youtube.com/embed/lkF0TQJO0bA
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: () {},
),
),
),
],
),