In Flutter, DropdownButtonFormField's modal list keeps growing to fill some height limit that seems to be ~90% of the screen (or possibly, and more likely, the Container it's in). When it reaches that limit, it becomes scrollable. Is it possible to set that height limit?
Here's the code I'm working with
Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Container(
padding: EdgeInsets.fromLTRB(5, 5, 5, 5),
child: Form(
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
//other widgets here
DropdownButtonFormField(items: this.dropDownItems),
],
),
)),
);
I was checking the code of DropDown and there is no property to set the height of the Dialog, it just fill almost the screen.
I made a small change to the class and you can include to your project if you want:
https://gist.github.com/tudor07/9f886102f3cb2f69314e159ea10572e1
Usage
1- Add the file into your project.
2- Import the file with an alias to avoid conflicts.
import 'custom_dropdown.dart' as custom;
3- Use the alias in your Widgets related to the DropDown, and add the height property:
Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Container(
padding: EdgeInsets.fromLTRB(5, 5, 5, 5),
child: Form(
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
//other widgets here
custom.DropdownButtonFormField(
height: 200.0,
items: this.dropDownItems),
],
),
)),
);
4- Don't forget to add the alias also in your DropdownMenuItem like this :
custom.DropdownMenuItem(
child: Text("Sample Tex"),
value: "any_value",
),
with this lines you can use DropdownButtonFormFieldlike a cheaps:
isDense: false,
itemHeight: 60,//what you need for height
so your code will be this :
Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Container(
padding: EdgeInsets.fromLTRB(5, 5, 5, 5),
child: Form(
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
//other widgets here
DropdownButtonFormField(items: this.dropDownItems
isDense: false,
itemHeight: 60,//what you need for height
),
],
),
)),
);
I spent over 30 minutes searching for answers!
I simply used the "menuMaxHeight" property of DropdownButton
It solved the problem
e.g
child: DropdownButton(
menuMaxHeight: 300,
This works!
DropdownButtonHideUnderline(
child: Container(
height: // some height,
padding: // add padding
decoration: // add decoration
child: DropdownButtonFormField(
decoration: InputDecoration.collapsed(hintText: ''),
// add some function according to you
),
),
)
**This container decoration is responsible for showing decoration in your dropDown button **
If you are using DropdownButton2 use dropdownMaxHeight: 300, for item list height
DropdownButtonHideUnderline(
child: DropdownButton2(
isExpanded: true, // For Expanded view (cover rest of the container width)
dropdownMaxHeight: 300, // For List Height
hint: ......
items: ......
)
)
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(...),
);
}
),
)
This question already has answers here:
Bottom overloaded by 213 pixels in flutter
(18 answers)
Closed 12 months ago.
I had an error "Bottom Overflowed by 199 pixel" when creating an Image inside the ListView, and after i google it, all of them suggest me to add:
resizeToAvoidBottomPadding: false
But, it doesnt work! The error is still there.
SafeArea widget is also doesnt solve the problem. Here is the short code version of my layout:
body: ListView(
children:<Widget> [
new Container(
child: new Stack(
children:<Widget> [
//THE WIDGET
new Container(), //THE BACKGROND IMAGE
new Positioned(
child: Column(
children:<Widget>[
new Transform(),
new FadeTransition(),
new FadeTransition(),
Divider(),
new Row(),
//THE IMAGE THAT I WANT TO ADD
new Container(
height: 360.0
decoration: BoxDecoration(
image: DecorationImage(
image: Assetimage('lake.jpg)
Use Scaffold property "resizeToAvoidBottomPadding: false" and "SingleChildScrollView" as parent of Scaffold body:
home: Scaffold(
resizeToAvoidBottomInset : false,
appBar: AppBar(
title: Text("Registration Page"),
),
body: SingleChildScrollView(
child: RegisterUserPage(),
)),
put your contents in a SingleChildScrollView and add ConstrainedBox like this:
body :SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(),
child: ListView(
children:<Widget> [
new Container(
child: new Stack(
children:<Widget> [
//THE WIDGET
new Container(), //THE BACKGROND IMAGE
new Positioned(
child: Column(
children:<Widget>[
new Transform(),
new FadeTransition(),
new FadeTransition(),
Divider(),
new Row(),
//THE IMAGE THAT I WANT TO ADD
new Container(
height: 360.0
decoration: BoxDecoration(
image: DecorationImage(
image: Assetimage('lake.jpg)
This is may make your screen scrollable and adding constraint will make it finite scroll.
Nothing, Just include your widget inside Expanded like this
Expanded(
child: sectionList(),
)
//this solved my issue
Using resizeToAvoidBottomInset: true, in Scaffold and wrapping the first child in the body with SingleChildScrollView solved my problem.
Just Use
SingleChildScrollView()
like as
body: SingleChildScrollView(
child: Column(
children: [
widgetClassSectionButton(),
listAttandance.isNotEmpty ? headLineContainer() : msgNothingToShow(),
listAttandance.isNotEmpty ? widgetStudentList():widgetMsgEmpty(),
CustomButton("Submit Data",context)
],
),
)
The parameter in scaffold works for me, envolve your widget for this error.
singlechildscrollview
This works for me for long form:
return Scaffold(
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(
child: IntrinsicHeight(
child: Form(
key: _formKey,
child: Column(...
This is How I solved it, adding a resizeToAvoidBottomInset: false, inside Scaffold() and using SingleChildScrollView() inside the body.
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.grey,
appBar: AppBar(
title: Text("Quotes"),
backgroundColor: Colors.green,
),
body: SingleChildScrollView(
child: Column(
children: quotes.map((quote) => quotesTemplete(quote)).toList(),
),
)
);
This aligns the item from bottom to top:
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
reverse: true,
I'm attempting to create a scrollable listview inside of a container which also contains a static image. However, the listview doesn't appear to be scrollable and I get a "bottom overflow by x pixels" artifact on my app.
static List<Widget> getClubs() {
var myClubs = new List<Widget>();
for (var i = 0; i < 10; i++) {
myClubs.add(new Padding(
padding: EdgeInsets.all(8.0),
child: new CircleAvatar(
backgroundImage:
new NetworkImage("https://i.imgur.com/p2oUDLD.png"),
backgroundColor: Colors.black,
radius: 34.0,
)));
}
return myClubs;
}
final leftSection = new Container(
color: Color(0xFF212121),
width: 100,
child: Column(
children: <Widget>[
SizedBox(height: 20.0),
new Image.asset(
'assets/logo.png',
alignment: Alignment.center,
),
SizedBox(height: 10.0),
new Container(
child: new ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(5.0),
children: getClubs(),
))
],
));
You can use Expanded widget or set the height for the Container.
I would also recommend Wrap for anyone running into an issue where a container is sized wrong within the listview, causing an overflow:
new Container(
alignment: Alignment.center,
child: Wrap( //the magic
children: [
new Container(),
],
),
),
Sometimes best way to fix an estimated height is using sizedbox
int heightToBeReduced = 380;
SizedBox(
height: MediaQuery.of(context).size.height - heightToBeReduced,
child: ListView....
)
wrap the Column in an Expanded widget:
Expanded(
child: Column(
),
),
Another way is to wrap the Column in a Flexible widget and specify a flex factor.
Flexible(
flex: 1,
child: Column(
children: [
],
),
),
I used a Flexible in a Row to control the output of the listview builder
Define the scollController
final _scrollController = ScrollController();
Define the ListView builder
ListView builder = ListView.builder(
itemCount: listPerformance?.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return PerformanceCardWidget(performanceView: listPerformance[index]);
});
Define a flexible that outputs the listview builder contents
Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
Flexible(
flex: 6,
fit: FlexFit.loose,
child: Scrollbar(
isAlwaysShown: true,
controller: _scrollController,
child: SingleChildScrollView(
controller: _scrollController, child: builder))
)
])
NOTE: Im using Navigator.of(context).push to push ModalRoute,
Hi I have page with ModalRoute with TextFormField in the body, but when keyboard show up, the input is being hide by keyboard, how to fix this?
return Container(
child: ListView(
children: <Widget>[
//other widget
SizedBox(height: _qtyAnimation.value),
Row(
children: <Widget>[
Expanded(
child: Text(
"Jumlah",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
SizedBox(
width: 145.0,
child: TextFormField(
focusNode: _qtyFocusNode,
controller: qty,
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(0.0),
prefixIcon: IconButton(
icon: Icon(Icons.remove),
onPressed: () {},
),
border: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey, width: 0.1),
),
suffixIcon: IconButton(
icon: Icon(Icons.add),
onPressed: () {},
),
),
),
),
],
),
],
);
thats my code, i try with focusnode and more, still same result
please help me
thanks solve my problem with this padding on bottom of textfield
Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom));
and mare reverse list
This worked for me...
First add this
final bottom = MediaQuery.of(context).viewInsets.bottom;
Then use a SingleChildScrollView() to wrap around the main widget (whatever you're using, e.g. Column, ListView, etc) like this...
You need "reverse: true"
Widget build{
return Scaffold(
body: SingleChildScrollView(
reverse: true;
child: Container(...
You also need these two lines of code for the Scaffold as well..
return Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
body: SingleChildScrollView(...
and finally, reference the 'bottom' for your EdgeInsets..
body: SingleChildScrollView(
reverse: true,
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: Container(...
You need to wrap everything in a SingleChildScrollView and set the reverse to true.
SingleChildScrollView(
reverse: true,
child: Container(),
);
Just that worked for me!
I had a similar problem. I try all solution, but didn't work.
Finally I removed
<item name="android:windowFullscreen">true</item>
from my styles.xml file in android folder, and fix the problem.
There are few methods for this (as of Dec 3rd 2018):
You can read this for a better solution: When i select a Textfield the keyboard moves over it.
Inside Scaffold() add: resizeToAvoidBottomPadding: false,.
You can also wrap your TextWidget with SingleChildScrollView(). This will allow you to scroll whenever the keyboard is shown.
Set resizeToAvoidBottomInset to false inside your Scaffold Widget.
Note that resizeToAvoidBottomPadding will be deprecated.
Scaffold( resizeToAvoidBottomInset: false, ...)
I use form elements in modal_bottom_sheet plugin. I solved it by just adding the following code to SingleChildScrollView.
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)
Too add to the commonly accepted answers here which is
body: SingleChildScrollView(
reverse: true,
child: Container(
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: Stack(
fit: StackFit.loose,
children: <Widget>[
I added a thing to the bottom inset to prevent it from going too high.
var bottom = MediaQuery.of(context).viewInsets.bottom;
bottom = max(min(bottom, 80), 0);
What worked for me was combining the docs with tips over here. It uses, LayoutBuilder, SingleChildScrollView, Padding (with bottom hack) and finally, ConstrainedBox (to use Expanded). By combining these It works with Expanded widgets inside Columns.
The docs (from where LayoutBuilder comes):
https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html
Structure
return Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,`
body: SafeArea(
child: Container(
child: LayoutBuilder(builder:
(BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
reverse: true,
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
maxHeight: viewportConstraints.maxHeight),
child: Column(
SingleChildScrollView does solve the problem while the resizeToAvoidBottomInset is set to true, while setting it to false would be a not recommended solution. Let me explain why:
When user presses the TextField, usually a virtual keyboard will popup and takes up a large portion of the bottom space on the screen. In such case, problem would occur, if the TextField is near said bottom, it will be covered by the keyboard (resizeToAvoid... set to false), and user will be unable to see what they've typed in; if there are other widgets below the TextField (when resizeToAvoid is true, e.g. buttons in the same Column with TextField), there will be overflow because there is no space for them to show on the remaining viewport.
Speaking from a user's perspective, what we want is:
TextField who gets focus is always visible.
No bottom overflow and bugged graphics.
However, such description is not technical, it does not tell us how exactly do we implement it. What we actually want is, make the whole layout scrollable, and allow Scaffold to resize. When the viewport resizes, anything below the focused TextField scrolls away to the invisible bottom, and the TextField itself snaps to the keyboard.That's why SingleChildScrollView + resize = true is what we want.
To have a centered content first on build method I added this:
final bottom = MediaQuery.of(context).viewInsets.bottom;
and return this:
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(
fit: StackFit.expand,
children: [
///Content
Align(
alignment: Alignment.center,
child: SingleChildScrollView(
reverse: true,
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: Column(
children: [
MyContent()
],
),
),
),
),
///Button
Align(
alignment: Alignment.bottomCenter,
child: MyBottomButton()
)
],
),
),
);
And it works very well with keyboard flow
In my case, there was were important to use only small padding, otherwise when open the keyboard it makes a big mess.
Padding(padding: EdgeInsets.only(bottom: 20)
Check my solution:
child: Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
body: Container(
color: Colors.black,
child: SingleChildScrollView(
reverse: true,
child: Padding(
padding: EdgeInsets.only(bottom: 20),
child: Container(
child: ReservationCard(
),
),
),
),
)
For Android, check for windowSoftInputMode. (AndroidManifest.xml)
android:windowSoftInputMode="adjustResize"
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.