tl;dr Why is space appearing between my two buttons when I have not explicitly set any?
I am trying to make a layout like the one below:
However, what appears to be about 16px of space appears between the two buttons and I cannot figure out where it is coming from.
I at first thought maybe the Column was adding space but I am using MainAxisAlignment.center which shouldn't add any. I now think that there is perhaps some Material theming going on that automatically applies padding to the RaisedButton, however I have looked through both button_theme.dart and raised_button.dart and it seemed like only the inner padding (between text and button edges) was being set. I'm sure I overlooked something and would appreciate any help in finding out why this space exists.
auth.dart (screen shown in the image)
...
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(flex: 2, child: Container()),
Expanded(
flex: 8,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.fromLTRB(0, 0, 0, 32),
child: Image(
fit: BoxFit.contain,
image: AssetImage('lib/res/drawable/logo.webp'))),
PrimaryButton(
onPressed: //...,
child: Text('Log In')),
PrimaryButton(
onPressed: //...,
child: Text('Sign Up')),
])),
Expanded(flex: 2, child: Container()),
]));
}
primary_button.dart (custom rounded button widget that extends RaisedButton):
...
Widget build(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(
textTheme: Theme.of(context).textTheme,
buttonTheme: Theme.of(context).buttonTheme.copyWith(
padding: EdgeInsets.all(0),
minWidth: double.infinity,
buttonColor: Theme.of(context).accentColor,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24))),
),
child: Builder(builder: super.build));
}
add the property materialTapTargetSize and set it to MaterialTapTargetSize.shrinkWrap.
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
if you check the source code of RawMaterialButton it adds a padding based on that value:
Size minSize;
switch (widget.materialTapTargetSize) {
case MaterialTapTargetSize.padded:
minSize = const Size(48.0, 48.0);
break;
case MaterialTapTargetSize.shrinkWrap:
minSize = Size.zero;
break;
}
return Semantics(
container: true,
button: true,
enabled: widget.enabled,
child: _InputPadding(
minSize: minSize,
child: result,
),
);
Related
I am making a settings page and the layout is a container with a set height and then under it a listview however this listview needs a set height; so it works when I wrap it in a container and give it a height however it doesn't work if I wrap it in a expanded.
I have tried many things like putting it in a layout builder and giving the height as BoxConstraints.maxHeight and a lot of other tricks which should work but don't.
class Settings extends StatelessWidget {
Settings({#required this.userInfo, #required this.licenseInfo});
final userInfo;
final licenseInfo;
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
SystemChannels.textInput.invokeMethod('TextInput.hide');
},
child: Scaffold(
resizeToAvoidBottomPadding: false,
backgroundColor: Colors.transparent,
appBar: AppBar(
elevation: 0.0,
backgroundColor: Color(0xFF77FDA7),
title: Text('Settings',
style: TextStyle(color: darkGrey, fontWeight: FontWeight.w600)),
),
body: Column(
children: <Widget>[
Stack(
children: <Widget>[
Container(
height: 91,
width: width,
decoration: BoxDecoration(gradient: greenGradient),
),
Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
SettingsProfile(
userInfo: this.userInfo,
licenseInfo: this.licenseInfo),
SizedBox(
height: 300,
child: SettingsList(),
),
],
),
],
),
],
)),
);
}
}
As you see there is a stack and another column however these are just parts of the UI and I need them. They do not have anything to do with me trying to fix this issue. PLEASE HELP as I need this listview to take up all available space in the column without overflowing.
I had a similar use-case and what I did on my app was wrap LayoutBuilder with Expanded. The LayoutBuilder fetches the dimensions of available screen space for the widget and it can be used to set the Widget's height.
Expanded(
child: LayoutBuilder(
builder: (BuildContext context,
BoxConstraints constraints) {
return Container(
height: constraints.maxHeight, // fetch height with Constraints
width: constraints.maxWidth,
child: ListView.builder(...),
);
}
),
)
I am trying to expand widget inside of Column widget but not able to make it expended.
When giving constant height to parent widget, the layout will be rendered as expected. But as I remove the constant height layout is not as expected as I want to make Listview with it and I should not give a constant height to the widget which will be used as listview item.
Below is my layout code.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'layout test',
home: Layout_test_class(),
));
}
class Layout_test_class extends StatelessWidget {
Widget cell() {
return Container(
color: Colors.yellow,
// height: 200, after un commenting this will work. but i want to make it without this
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Container(
color: Colors.green,
child: Text('apple z'),
),
),
Container(
color: Colors.red,
child:Text('apple 2'),
)
],
),
),
Column(
children: <Widget>[
Container(
color: Colors.black,
width: 200,
height: 200,
),
],
),
],
),
);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('title'),
),
body: Center(
child: ListView(
children: <Widget>[
cell(),
],
)
),
);
}
}
Below is my expected output screenshot.
Try to wrap your Container with IntrinsicHeight
return IntrinsicHeight(
Container(
color: Colors.yellow
child: ...
)
)
Your ListView needs to be inside Flexible. Flexible inside Column will set maximum height available to ListView. ListView needs a finite height from parent, Flexible will provide that based on max. space available.
Column(
children: <Widget>[
Flexible(
child: ListView.builder(...)
),
Container(
color: Colors.red,
child:Text('apple 2'),
),
],
)
A nice way of doing this, it's to play with the MediaQuery, heigth and width.
Let me explain, if you want the widget to have the maximum heigth of a decide screen, you can set it like this:
Container(
height: MediaQuery.of(context).size.height // Full screen size
)
You can manipulate it by dividing by 2, 3, 400, the value you want.
The same things works for the width
Container(
width: MediaQuery.of(context).size.width // Can divide by any value you want here
)
Actually quite the opposite, if you're planning to use this as an item in a listViewyou can't let infinite size on the same axis your listView is scrolling.
Let me explain:
Currently you're not defining any height on your cell() widget, which is fine if you're using it alone. like this :
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'layout test',
home: Layout_test_class(),
));
}
class Layout_test_class extends StatelessWidget {
Widget cell() {
return Container(
color: Colors.yellow,
//height: 250, after un commenting this will work. but i want to make it without this
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Container(
color: Colors.green,
child: Text('apple z'),
),
),
Container(
color: Colors.red,
child: Text('apple 2'),
)
],
),
),
Column(
children: <Widget>[
Container(
color: Colors.black,
width: 200,
height: 200,
),
],
),
],
),
);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('title'),
),
body: cell(),
);
}
}
But using it with a listView you have to define a height. A listView scrolls as long as it have some content to scroll. Right now it just like you're giving it infinite content so it would scroll indefinitely. Instead Flutter is not constructing it.
It's actually quite ok to define a global size for your container (as an item). You can even define a specific size for each using a parameter like this :
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'layout test',
home: Layout_test_class(),
));
}
class Layout_test_class extends StatelessWidget {
Widget cell(double height) {
return Container(
color: Colors.yellow,
height: height, //after un commenting this will work. but i want to make it without this
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Container(
color: Colors.green,
child: Text('apple z'),
),
),
Container(
color: Colors.red,
child: Text('apple 2'),
)
],
),
),
Column(
children: <Widget>[
Container(
color: Colors.black,
width: 200,
height: 200,
),
],
),
],
),
);
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('title'),
),
body: ListView(
children: <Widget>[
cell(250.0),
cell(230.0),
cell(300.0),
],
)
);
}
}
I want to center a Text vertically in the bottom: Sektion of my AppBar.
Some things I allready tried are:
1. wrap the Text in a Center(...) Widget
2. wrap the Text in a Column(...) and use crossAxisAlignment: CrossAxisAlignment.center
The bottom: Sektion is a PreferredSizeWidget and does not provide anything to format a Widget.
appBar: new AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
print("Settings Icon");
},
),
],
bottom: PreferredSize(
preferredSize: Size(130.0, 130.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Text(
'N/A',
),
],
),
),
),
I have have found this issue here: https://github.com/flutter/flutter/issues/16262 where the Text was centered but the reproduce code did not worked out for me.
The Text should me somewhere like the red line is (see Image)
Thank you!
PreferredSizeWidget does not impose a size constraint on its child, so you must wrap the Column in a widget with defined height in order to add alignment.
Also, mainAxisAlignment should be used, since this is the vertical alignment in a Column.
bottom: PreferredSize(
preferredSize: Size(130.0, 130.0),
child: Container(
height: 130,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'N/A',
),
],
),
),
)
I am trying to make a simple chat app, so I created a scaffold and my body, will be the messages and my bottomNavigationBar would be my typing field and sending icon.
I added a text field but when typing the navigation bar is hidden by the keyboard.
this is the code of my BottomNavigationBar :
bottomNavigationBar: new Container(
height: ScreenSize.height/12,
/*color: Colors.red,*/
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new Container(
child: new Icon(Icons.send),
width:ScreenSize.width/6,
),
],
),
new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Material(
child: new Container(
child: new TextField(
autofocus: false,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(9.0),
border: InputBorder.none,
hintText: 'Please enter a search term',
),
),
width:ScreenSize.width*4/6,
),
elevation: 4.0,
/*borderRadius: new BorderRadius.all(new Radius.circular(45.0)),*/
clipBehavior: Clip.antiAlias,
type: MaterialType.card,
)
],
),
new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
new Container(
child: Text('HELLO C1'),
color: Colors.green,
width:ScreenSize.width/6,
),
],
)
],
),
),
here is how it looks when focused :
if you use a Stack on your Scaffold's body, instead of bottomNavigationBar, your nav will push up above the keyboard. even if you fix to the bottom with a Positioned:
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: MyNav(),
),
simply wrap your bottom navigation bar with Padding and set it to MediaQuery.of(context).viewInsets,
bottomNavigationBar: Padding(
padding: MediaQuery.of(context).viewInsets,
child: ChatInputField(),
),
Literally just worked through the same issue. Given the code i was refactoring, this worked like a charm. Peep the github link, review his change and apply. Couldn't be much more straight forward: https://github.com/GitJournal/GitJournal/commit/f946fe487a18b2cb8cb1d488026af5c64a8f2f78..
Content of the link above in case the link goes down:
(-)BottomAppBar buildEditorBottonBar(
(+)Widget buildEditorBottonBar(
BuildContext context,
Editor editor,
EditorState editorState,
BottomAppBar buildEditorBottonBar(
folderName = "Root Folder";
}
*REPLACE* return BottomAppBar(
elevation: 0.0,
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.folder),
label: Text(folderName),
onPressed: () {
var note = editorState.getNote();
editor.moveNoteToFolderSelected(note);
},
)
],
mainAxisAlignment: MainAxisAlignment.center,
*WITH THE WRAPPER* return StickyBottomAppBar(
child: BottomAppBar(
elevation: 0.0,
color: Theme.of(context).scaffoldBackgroundColor,
child: Row(
children: <Widget>[
FlatButton.icon(
icon: Icon(Icons.folder),
label: Text(folderName),
onPressed: () {
var note = editorState.getNote();
editor.moveNoteToFolderSelected(note);
},
)
],
mainAxisAlignment: MainAxisAlignment.center,
),
),
);
}
class StickyBottomAppBar extends StatelessWidget {
final BottomAppBar child;
StickyBottomAppBar({#required this.child});
#override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(0.0, -1 * MediaQuery.of(context).viewInsets.bottom),
child: child,
);
}
}
I achieved this by a mix of two things I found separated in the web:
1 - Inside the Scaffold, I put other with only a bottomNavigationBar with a empty Container. For some reason, this trick push all my real bottomNavigationBar up to the top of the keyboard.
Scaffold(
bottomNavigationBar: Container(
height: 0,
),
body: Scaffold(
body: MyWidget(
But, I did not want all the content up, so I got that Package:
2 - I added flutter_keyboard_visibility: ^5.1.0 from
https://pub.dev/packages/flutter_keyboard_visibility
With this Package, you can do anything you want in response to keyboard visibility - is up to you. In my case, I made all content of my real bottomNavigationBar disappear except the textfield, which stay on the top of the keyboard:
[TextFormField] // dont go away,
//The others:
KeyboardVisibilityBuilder(builder: (context, visible) {
return Column(
children: [
visible
? SizedBox(
height: 0,
)
: OtherWidgets(
If you need some kind of button; you can do:
Scaffold(
bottomNavigationBar: bottomNavigationBar,
floatingActionButton: ExampleButton(
text: 'Hello',
),
body: body,
),
You can apply further customizations on the Floating Action Button using parameters in the Scaffold.
There is a simple way to do this if you want to really need to use the bottom navigation bar of the scaffold to put your widgets in rather than put it on a stack. Just wrap your scaffold with another scaffold and it should solve the problem.
return Scaffold(
body: Scaffold(
bottomNavigationBar: yourBottomNavigationBarWidget(),
body: yourBody(),
This works best especially when the height of your widget changes dynamically (because the text user types may introduce multiple lines) and you want the body to resize accordingly. A body in the stack, as suggested by many, will require a bottom padding to be visible over the text field and need to change dynamically as user types which is difficult to handle when you have multiple widgets sitting in and around the text field.
I'm trying to show a text in multiple lines, I mean like this:
"I am a text
and I finish here"
When I try to do that, I see a bar that says "Right Overflowed by 443 pixels".
I have this UI structure:
#override
Widget build(BuildContext context) {
return Card(
child: Scaffold(
body: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(15.0),
child: Image.asset('images/place.png'),
)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 15.0),
child: Text(
_placeCard.description,
style: TextStyle(),
softWrap: true
)
)
],
),
],
),
)
);
}
Where _placeCard.description is something like : "nce thethethe the the the 1500s, when an unknown printer took a galley of type and scrambled it to"
Could someone help me or give me any feedback?
Wrap your Text widget using a Flexible widget.
like,
//updated read: aziza comment
Flexible(//newly added
child: Container(
padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 15.0),
child: Text(
_placeCard.description,
style: TextStyle(),
softWrap: true
),
)
)
A simple example in below link:
https://gist.github.com/Blasanka/264510a0e7e5aaa151f02ada19fd466d
Update:
Above solution wraps the Text widget but in your question code snippet, the problem is you are using two Columns inside a Row and you havent added constraint. So, the easy solution to wrap those two Column widget using Flexible widgets.
like below,
Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: Column(
//...
),
),
Flexible(
child: Column(
//...
),
),
],
),
Try wrapping your text widget in Expanded class and set it's flex factor. It will force the text to fit within the container.
Card(
color: kBoxColor,
child: Row(
children: [
Icon(Icons.description),
SizedBox(width:20.0),
Expanded(
flex: 30,
child: Text(
// Extremely long text,
style: kAnsTextStyle,
),
),
],
),
),