How to have a Flutter button be as wide as possible up to a maximum width? - button

In the following layout, I'd like the button to be able to grow to be as wide as possible on the screen, up to a maximum width. I've tried the following, which doesn't work (the button is always as wide as possible):
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(),
TextFormField(),
ConstrainedBox(
constraints: BoxConstraints(maxWidth: 200),
child: RaisedButton(child: Text("button"), onPressed: () {}),
),
],
),
),
),
),
);
}
}
To expand on the layout I'm looking for: the button must be the same width as the smaller of the following two quantities: 1) the width of the screen, 2) a given fixed maximum width.
Example scenarios:
A) the screen is 1000 pixels wide, and the given fixed maximum width is 600 pixels, then the button will be 600 pixels wide.
B) the screen is 400 pixels wide, and the given fixed maximum width is 600 pixels, then the button will be 400 pixels wide.

The solution is pretty simple, simply wrap your ConstrainedBox in Align and instead of using maxWidth use minWidth.
Align(
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: 200),
child: RaisedButton(child: Text("button"), onPressed: () {}),
),
)
Output:
If screen width > 200, button takes up 200 width
If screen width < 200, button takes up screen width

You can remove crossAxisAlignment: CrossAxisAlignment.stretch, because TextFormField is stretching anyway. This code will make the button width to be of a max width size, but no bigger than screen width:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) => MaterialApp(
home: Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
TextFormField(),
TextFormField(),
Container(
width: 200,
child: RaisedButton(
onPressed: () {},
child: Text('button'),
),
),
Container(
width: 200,
child: RaisedButton(
onPressed: () {},
child: Text(
'Button with long text asf sadf sdf as df s df as '
'dfas dfsd f asfauhiusg isdugfisudgfi asudgk usgkdu'
'ksdfhk sudfhk sudhfk',
),
),
),
],
),
),
),
),
);
}

You can put the RaisedButton in a Row:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(),
TextFormField(),
ConstrainedBox(
constraints: BoxConstraints(maxWidth: 250),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(child: Text('test')),
),
],
),
),
],
),
),
),
),
);
}
}
The Row will create a horizontal row, and the RaisedButton widget will only take as much room as its own size.

first wrap with container and add width to infinity to be responsive:
Container(
width: double.infinity,
child: ElevatedButton(
child: Text("button"),
onPressed: (){}
),
),
you can add padding too..
known that RaisedButton is deprecated and migrated to ElevatedButton..

Related

How can I resolve "A RenderFlex overflowed by 77 pixels on the bottom."

I have this error with that code code :
import 'package:flutter/material.dart';
import 'package:yummy/main.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
backgroundColor: Colors.white,
leading: IconButton(
icon: Image.asset("doodles/theuser.png"),
onPressed: (){},
),
centerTitle: true,
title: Image.asset("doodles/halfyummylog.png"),
actions: <Widget>[
IconButton(onPressed: (){}, icon: Image.asset(("doodles/favrec.png")))
],
),
body: Container(
width: MediaQuery.of(context).size.width,
height: 100,
color: Color(0xFFFFDEE2),
child: Column(
children: <Widget>[
Image.asset("doodles/DinnerPlace.png"),
SizedBox(
height: 30,
), Container(
decoration: BoxDecoration(color : Colors.white, borderRadius: BorderRadius.circular(14)),
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: Icon(Icons.search,color: Colors.grey,size : 33),
hintText: "Search",
hintStyle: TextStyle(
fontFamily: "SFProDisplay",
color : Colors.grey,
fontSize: 20.0
),
),
)),
],
),
),
);
}
}
The error pop at the bottom of the image "doodles/DinnerPlace.png" after the appbar and I don't know why.
If somoene can help me for resolve this I will be really greatful.
As your container of the body is 100, you have to bound the image within this height.But the height of Image is not specified, so it take the space more than body's container's 100.So either bound the image with container with height like this -
Container(
height: 70,
child: Image.asset("doodles/DinnerPlace.png"),
)
or increase the size of body's Container from 100 to 200.
The problem was because of the second container I just add an Expanded widget for the container and it's working properly now.

Align buttons below appBar without any space in flutter [duplicate]

This question already has answers here:
Unwanted space appearing between RaisedButton widgets in a column
(1 answer)
Flutter: Remove padding in buttons - FlatButton, ElevatedButton, OutlinedButton
(11 answers)
Closed 3 years ago.
I want to align the buttons just below the appBar but I am getting this:
I want to remove the space between buttons and the appBar. How can I achieve this?
This is the code:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Home',
),
),
body: Column(
children: <Widget>[
Row(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*0.5,
child: RaisedButton(
onPressed: (){},
child: Text('SORT'),
),
)
],
),
Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*0.5,
child: RaisedButton(
onPressed: (){},
child: Text('FILTER'),
),
)
],
)
],
),
],
),
);
}
}
Inside the RaisedButton, add this argument:
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap
Use a widget Align parent :
appBar: AppBar(
title: Align(
alignment: Alignment.center
Text(
'Home',
),
),
),

Flutter: aligning buttons edge to edge to other components

I found it difficult to layout buttons in a way that their visual representation is harmonic with other widgets, yet their touchable area has additional extra space for users' fingers.
Please have a look at the attached picture.
Code:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Material(child: HomePage()),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
Container(
color: Colors.yellow,
padding: EdgeInsets.all(16),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('Top Left'),
Spacer(),
Text('Top right')
],
),
Row(
children: <Widget>[
Text('Middle Left'),
Spacer(),
Text('Middle right')
],
),
Row(
children: <Widget>[
Text('Bottom Left'),
Spacer(),
Text('Bottom right')
],
),
],
),
),
Container(
color: Colors.orange,
padding: EdgeInsets.all(16),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text('Top Left'),
Spacer(),
FlatButton(
child: Text('Top right'),
onPressed: () {},
)
],
),
Row(
children: <Widget>[
Text('Middle Left'),
Spacer(),
Text('Middle right')
],
),
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.print),
onPressed: () {},
alignment: Alignment.bottomLeft,
),
Spacer(),
Text('Bottom right')
],
),
],
),
),
],
),
);
}
}
The "all texts" widgets are beautifully aligned. But when I add interactive widgets, it starts getting ugly.
The Flat button has the same font as Text. But it's touchable area is expanding it. I am aware of materialTapTargetSize but it shrinks the clickable area which has its inflated size to make it easy to tap it. Is there an easy way to render it exactly as the "Top right" text widget and still have the same touchable area? In that case, the touchable area should expand further out of 16px padding, because I would link the Ink to be distributed evently around the button.
IconButton is higher than text, but the problem is that it doesn't start where the texts starts (left edge). Even if I add the alignment: Alignment.centerLeft, it is slightly moved to the left but still not edge to edge with other texts. On top of that after changing this alignment it's no longer centred within its InkWell.
For now, I solve all these issues using Stack and Positioned widgets. With this approach, I can control exactly where the items are, and the InkWell keeps the content exactly in the centre. But I believe it's not a correct solution.
Appreciate your feedback.
Try this code,
For the flat button:
Container(
alignment: Alignment.centerRight,
width: 60,
child: FlatButton(
padding: EdgeInsets.all(0),
child: Text('Top right'),
onPressed: () {},
),
)
For the icon button:
IconButton(
padding: EdgeInsets.all(0),
icon: Icon(Icons.print),
onPressed: () {},
alignment: Alignment.bottomLeft,
),

overflowing RenderFlex flutter

I am trying to make a seemingly easy page with flutter.
It contains of totally five rows where row 1 & 2, 3 & 4 belongs together, and the last row is its own.
Row 1: Centered text
Row 2: 8 icon buttons
Row 3: Centered text
Row 4: 5 checkboxes
Row 5: Text with a following icon button
The problem I get is the size:
I/flutter (22610):◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢
A RenderFlex overflowed by 248 pixels on the right.
I have tried to make the code in different classes, according to their belonging, but then I get this error.
When I tried to put the code in containers, the iconButtons and checkBoxes quit working. I have read a lot of questions about similar problems here on Stackoverflow and googled around about it, but I'm still stuck.
class MyIcon extends StatefulWidget {
#override
_MyIconState createState() => _MyIconState();
}
class _MyIconState extends State<MyIcon> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.red,
// body: Container(
// height: 180.0,
// color: Colors.lightBlueAccent,
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 50.0),
),
Text(
'FIRST TEXT',
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 25.0,
color: Colors.white,
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
// Padding(padding: EdgeInsets.only(left: 3.0, right: 10.0)),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
_IconButtons(
headImageAssetPath: 'assets/ico.png',
onPressed: () {},
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"SECOND TEXT'",
style: TextStyle(fontSize: 25.0, color: Colors.white),
),
],
),
MyCheckBox(),
],
),
// ),
);
}
}
class _IconButtons extends StatelessWidget {
final iconSize = 60.0;
final String headImageAssetPath;
final onPressed;
_IconButtons({this.headImageAssetPath, this.onPressed});
#override
Widget build(BuildContext context) {
return IconButton(
iconSize: iconSize,
icon: Image.asset(headImageAssetPath),
onPressed: () {});
}
}
class MyCheckBox extends StatefulWidget {
#override
_MyCheckBoxState createState() => _MyCheckBoxState();
}
class _MyCheckBoxState extends State<MyCheckBox> {
#override
Widget build(BuildContext context) {
return Expanded(
child: Column(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Text(
"ANOTHER TEXT",
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 25.0,
color: Colors.blueGrey,
),
),
],
),
),
],
),
);
}
}
This is one of many tries. If you want I can send the code for the checkboxes too. (I'm new to flutter so I'm sorry if my code is bad).
Any help is appreciated. Thank you.
In the row 2, every button icon width valued 60, then the Row container will width valued 60 * 8 = 480 at least, so the error occurs.
I have two solutions for you:
If you want to keep the button size width valued 60, you can replace Row with Wrap, the button will start a new row when it meet the edge of the screen.
If you want the 8 buttons placed in one single row, you can wrap the IconButton with Expanded
return Expanded(child:IconButton(
iconSize: iconSize,
icon: Image.asset(headImageAssetPath),
onPressed: () {}
));

Flutter Change height of an OutlineButton inside an AppBar?

Just wondering how I would change the height of an OutlineButton? I suppose this would likely apply to other button types as well.
return Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget> [
SizedBox(
width: 100.0,
height: 8.0,
child: OutlineButton(
borderSide: BorderSide(width: 4.0)
child: Text('Hi'),
onPressed: (){},
),
),
],
),
body: Container(),
);
I am finding the button just about 8px too high for my case, and want to squish it a bit.
SizedBox should do the work. Wrap your button by a SizedBox.
From the document:
If given a child, this widget forces its child to have a specific width and/or height (assuming values are permitted by this widget's parent). If either the width or height is null, this widget will size itself to match the child's size in that dimension.
If not given a child, this widget will size itself to the given width and height, treating nulls as zero.
This will work for RaisedButton also
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Layout',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("SizedBox Demo"),
),
body: new Center(
child: new SizedBox(
width: 200.0,
height: 80.0,
child: new OutlineButton(
borderSide: BorderSide(width: 4.0),
child: Text('I am a button'),
onPressed: (() {})),
),
),
);
}
}
UPDATED (2018/05/26):
If you want to reduce the height of OutlineButton inside AppBar, use Padding
return Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget> [
Padding(
child: OutlineButton(
borderSide: BorderSide(width: 4.0)
child: Text('Hi'),
onPressed: (){},
padding: EdgeInsets.all(10.0),
),
),
],
),
body: Container(),
);
Flutter 2.5
OutlineButton is deprecated. Instead, use the Material button.
Put the Material Button inside Padding.
The padding property of Padding will control the height and width of the button.
AppBar(
title: Text("Stack Overflow"),
actions: [
Padding(
padding: EdgeInsets.all(8.0),
child: MaterialButton(
color: Colors.yellow,
onPressed: () {
},
child: Text('SUBMIT'),
),
)
],
)
Thanks #phuc-tran, I've made a small fix:
return Scaffold(
appBar: AppBar(
title: Text('Test'),
actions: <Widget> [
Padding(
padding: EdgeInsets.all(10.0),
child: OutlineButton(
borderSide: BorderSide(color: Colors.blue),
child: Text('Hi'),
onPressed: (){},
),
),
],
),
body: Container(),
);

Resources