I am trying to increase my text field height but it's not increasing I already try wrapping with the container and increase the height of the container but it just increases the background height not text field height.
Also maxLines is working but needs to increase by height so I can add some shadows in container
import 'package:flutter/material.dart';
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
import 'package:mytravel/screens/loginPage.dart';
import 'package:mytravel/screens/guidePlacePage.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:async';
import 'dart:io';
class addPostPage extends StatefulWidget {
#override
_addPostPageState createState() => _addPostPageState();
}
class _addPostPageState extends State<addPostPage> {
File _image;
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFEDF0F6),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 75, right: 10, left: 10),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(25.0),
),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Column(
children: <Widget>[
InkWell(
onTap: () {
getImage();
},
child: Container(
margin: EdgeInsets.all(10.0),
width: double.infinity,
height: 400.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
boxShadow: [
BoxShadow(
color: Colors.black45,
offset: Offset(0, 5),
blurRadius: 8.0,
),
],
image: DecorationImage(
image: _image == null
? AssetImage("assets/images/post0.jpg")
: Image.file(_image),
fit: BoxFit.fitWidth,
),
),
),
),
],
),
),
Container(
height: 200, //here you can see try to increase height
padding: EdgeInsets.only(right: 15, left: 15),
child: TextField(
style: TextStyle(
fontSize: 20,
),
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
fillColor: Colors.white,
filled: true,
border: InputBorder.none,
hintText: 'Your short story of image',
),
),
)
],
),
),
),
],
),
),
);
}
}
the contentPadding controls the height of the TextField if you want to increase the height of your text then you would alter the height property in TextStyle
TextField(
style: TextStyle(height: 4 // controls the height on main text
),
controller: _controller,
decoration: InputDecoration(
contentPadding: // Text Field height
EdgeInsets.symmetric(
vertical: 25.0, horizontal: 10.0),
hintStyle: TextStyle(
height: 4, //Controls the height of the hint text
),
errorStyle:
TextStyle(), // Controls style of error message
counterStyle:
TextStyle(), //Controls style of the counter if you have one
helperStyle:
TextStyle(), //Controls style of the helper message
labelStyle:
TextStyle(), //Controls style of the label message
prefixStyle:
TextStyle() //Controls the style of the prefix
),
),
let me know if this works
First Option: (Make sure to match the height)
TextField(
style: TextStyle(
height: 1.5, // change this to reflect the effect
fontSize: 20.0
),
hintStyle: TextStyle(
height: 1.5, //Controls the height of the hint text
),
)
Second Option:
TextField(
decoration: const InputDecoration(
contentPadding: const EdgeInsets.symmetric(vertical: 40.0),
)
)
Plus wcyankees424 answer provides more options, even for success,error etc. hints.
Read this page please:
https://api.flutter.dev/flutter/painting/TextStyle/height.html
As it is described you need add a height property for text. So you need add this line after font size:
height:2.0;
When height is null or omitted, the line height will be determined by the font's metrics directly, which may differ from the fontSize. When height is non-null, the line height of the span of text will be a multiple of fontSize and be exactly fontSize * height logical pixels tall.
Related
I have the following code:
containers.add(Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue,
),
margin: const EdgeInsets.all(10),
width: MediaQuery.of(context).size.width/2-20,
height: MediaQuery.of(context).size.width/2-20,
child: Column(
children: [
Text(
value2,
style: TextStyle(
inherit: false,
color: Colors.white,
fontSize: MediaQuery.of(context).size.width/2,
fontWeight: FontWeight.bold,
)
),
]
)
));
});
}
});
The container itself goes into a list which is passed into a GridView eventually becoming a 2-wide grid down the screen. I want to make it so that the text height is half of the height of the container defined by the width and height MediaQuery.of(context).size.width/2-20. Is this possible?
Thanks
You can use Expanded together with FittedBox:
class HalfHeightText extends StatelessWidget {
final String label;
const HalfHeightText({required this.label});
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue,
),
margin: const EdgeInsets.all(10),
width: MediaQuery.of(context).size.width / 2 - 20,
height: MediaQuery.of(context).size.width / 2 - 20,
child: Column(
children: [
// ===========================================
Expanded(
child: FittedBox(
fit: BoxFit.contain,
child: Text(
label,
style: const TextStyle(
inherit: false,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
const Expanded(child: SizedBox.shrink()),
// ===========================================
],
),
);
}
}
Result:
HalfHeightText(label: "Text")
use
width: MediaQuery.of(context).size.width0.50,
its mean like user of width 50% or else MediaQuery.of(context).size.width0.25, mean 25%
I want to scroll the loginform but NOT the background, but i noticed that the cointaner that contains these "circles" are moved to the up when keyboards appears, so i added
resizeToAvoidBottomInset: true,
To the scaffold, but now i cant scroll anything in the loginform and thats is what i dont want, i want to scroll ONLY the loggin form..
Here is the screenshot of the emulator, just click this
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:landscapes/bloc/inherited_provider.dart';
import 'package:landscapes/bloc/login_bloc.dart';
import 'package:landscapes/pages/register_page.dart';
class LoginPage extends StatefulWidget {
LoginPage({Key key}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Form(
key: formKey,
child: Stack(
children: <Widget>[
_crearFondo(),
_loginForm(context),
],
),
));
}
Widget _crearFondo() {
Size size = MediaQuery.of(context).size;
final fondoGris = Container(
height: size.height, width: size.width, color: Colors.grey[850]);
final circulo = Container(
width: 90.0,
height: 90.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100.0),
color: Color.fromRGBO(255, 255, 255, 0.05)),
);
return Stack(
children: <Widget>[
fondoGris,
Positioned(top: 50.0, left: 30.0, child: circulo),
Positioned(top: 150.0, right: 50.0, child: circulo),
Positioned(bottom: 180.0, right: 20.0, child: circulo),
Positioned(bottom: 280.0, left: 40.0, child: circulo),
],
);
}
Widget _loginForm(context) {
final bloc = InheritedProvider.loginBlocInherit(context);
final size = MediaQuery.of(context).size;
return SingleChildScrollView(
child: Column(
children: <Widget>[
SafeArea(child: Container(height: size.height * 0.05)),
SizedBox(height: size.height * 0.05),
welcomeBackForm(),
SizedBox(height: 55.0),
_formEmail(bloc),
SizedBox(height: 30.0),
_formPassword(),
SizedBox(height: 38),
_button(),
SizedBox(height: 50),
_crearCuenta(),
],
),
);
}
//MENSAJE BIENVENIDA
Widget welcomeBackForm() {
return Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(left: 40.0),
child: Text(
'Hello!\nWelcome back',
style: GoogleFonts.playfairDisplay(
fontSize: 30, fontWeight: FontWeight.w600, color: Colors.white),
),
);
}
//TEXTFORMFIELD DEL EMAIL
Widget _formEmail(LoginBloc bloc) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Email adress',
filled: true,
fillColor: Colors.grey[600],
enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
border: OutlineInputBorder(borderSide: BorderSide.none)),
style: TextStyle(height: 1),
validator: (value) {
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regExp = new RegExp(pattern);
if (regExp.hasMatch(value)) {
return null;
} else {
return ('El email no es correcto');
}
},
),
);
}
//TEXTFORMFIELD DEL PASSWORD
Widget _formPassword() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 30.0),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.white,
),
hintText: 'Password',
filled: true,
fillColor: Colors.grey[600],
enabledBorder: OutlineInputBorder(borderSide: BorderSide.none),
border: OutlineInputBorder(borderSide: BorderSide.none),
),
style: TextStyle(height: 1),
),
);
}
//BOTON INGRESAR
Widget _button() {
return RaisedButton(
color: Color.fromRGBO(254, 200, 140, 1),
padding: EdgeInsets.symmetric(horizontal: 90.0, vertical: 15.0),
child: Text('ingresar'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
elevation: 0.0,
onPressed: () => _submit(),
);
}
//FLATBUTTON DE CREAR CUENTA
Widget _crearCuenta() {
return FlatButton(
onPressed: () => Navigator.pushReplacementNamed(context, 'registerpage'),
child: Text(
'Crear una nueva cuenta',
style: TextStyle(fontSize: 14),
),
textColor: Colors.white,
);
}
//SUBMIT DEL BOTON
void _submit() async {
if (!formKey.currentState.validate()) return null;
formKey.currentState.save();
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (BuildContext context) => RegisterPage()));
// Navigator.pushReplacementNamed(context, HomePage.routName).then((value) { setState(() { });});
}
}
You may try wrapping your _loginForm with SingleChildScrollView as follows :
SingleChildScrollView(child: _loginForm(context)),
By doing so the widgets within _crearFondo() will not scroll, however the widgets within _loginForm will scroll.
Please review the Flutter Documentation for SingleChildScrollView
SingleChildScrollView
A box in which a single widget can be scrolled.
This widget is useful when you have a single box that will normally be
entirely visible, for example a clock face in a time picker, but you
need to make sure it can be scrolled if the container gets too small
in one axis (the scroll direction).
It is also useful if you need to shrink-wrap in both axes (the main
scrolling direction as well as the cross axis), as one might see in a
dialog or pop-up menu. In that case, you might pair the
SingleChildScrollView with a ListBody child.
When you have a list of children and do not require cross-axis
shrink-wrapping behavior, for example a scrolling list that is always
the width of the screen, consider ListView, which is vastly more
efficient that a SingleChildScrollView containing a ListBody or Column
with many children.
I can't figure out how to get past the 48px Material library default. I did a quick scan through the SDK and couldn't find anything. I know it's something to do with the prefixIcon parameter itself because it will always be 48px or whatever it is no matter what is placed inside.
I have a custom SDK so if anyone knows where it is I'd like to reduce it because it always just gets in the way.
// : Searchbar Decoration
static InputDecoration searchbarDecoration = InputDecoration(
prefixIcon: Icon(
Icons.search,
color: DocumentColours.colour10,
),
contentPadding: EdgeInsets.symmetric(
vertical: 0.0,
horizontal: 0.0,
),
fillColor: DocumentColours.colour8,
filled: true,
labelText: 'Search',
labelStyle: FontStyles.searchbarLabel,
hasFloatingPlaceholder: false,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
borderSide: BorderSide(width: 0.0, style: BorderStyle.none),
),
);
NOTE: To solve this, use the prefixIconConstraints property of the InputDecoration as of SDK version 1.17.0
Below is what the documentation says (1.17.0) input_decorater.dart:
BoxConstraints can be used to modify the surrounding of the prefixIcon.
This property is particularly useful for getting the decoration's height less than 48px. This can be achieved by setting [isDense] to true and
setting the constraints' minimum height and width to a value lower than 48px.
Check the code below: It works perfectly:
TextField(
decoration: InputDecoration(
// choose any icon of your choice here
prefixIcon: Icon(Icons.person),
// set the prefix icon constraints
prefixIconConstraints: BoxConstraints(
minWidth: 25,
minHeight: 25,
),
),
),
I hope this helps.
My way is to custom my own textfield component using Row > Icon + TextField, just forget there is a prefixIcon in TextField.
like:
Container(
width: 200.0,
height: 40.0,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(3.0),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
left: 13.0,
right: 6.0,
),
child: Icon(
Icons.search,
size: 16.0,
),
),
TextField(
// ...
),
],
),
),
When the error message shows up, it reduces the height of the TextFormField. If I understood correctly, that's because the height of the error message is taking into account in the height specified.
Here's a screen before :
and after :
Tried to put conterText: ' ' to the BoxDecoration (as I've seen on another topic) but it didn't help.
An idea ?
EDIT : OMG completly forgot to put the code, here it is :
return Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
height: 40.0,
child: _createTextFormField(loginEmailController, Icons.alternate_email, "Email Adress", false, TextInputType.emailAddress),
),
Container(
height: 40.0,
child: _createTextFormField(loginPasswordController, Icons.lock, "Password", true, TextInputType.text),
),
SizedBox(
width: double.infinity,
child: loginButton
)
],
),
);
}
Widget _createTextFormField(TextEditingController controller, IconData icon, String hintText, bool obscureText, TextInputType inputType){
return TextFormField(
keyboardType: inputType,
controller: controller,
obscureText: obscureText,
/* style: TextStyle(
fontSize: 15.0,
), */
decoration: InputDecoration(
/* contentPadding:
EdgeInsets.symmetric(vertical: 5.0, horizontal: 8.0), */
border: OutlineInputBorder(borderRadius: BorderRadius.circular(5.0)),
icon: Icon(
icon,
color: Colors.black,
size: 22.0,
),
//hintText: hintText,
labelText: hintText,
),
validator: (value) {
if (value.isEmpty) {
return 'Enter some text';
}
return null;
},
);
}
In your Code - you need to comment out the 40 height given to each container.
Container(
// height: 40.0,
child: _createTextFormField(
loginEmailController,
Icons.alternate_email,
"Email Adress",
false,
TextInputType.emailAddress),
),
Container(
// height: 40.0,
child: _createTextFormField(loginPasswordController, Icons.lock,
"Password", true, TextInputType.text),
),
and then in your - TextFormField in InputDecoration, you can alter these value as per your liking.
contentPadding:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
Above solutions did not work for me however I have figured out a very simple solution to avoid the above issue
TextFormField(
decoration: InputDecoration(
**errorStyle: const TextStyle(fontSize: 0.01),**
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(borderRadius),
borderSide: const BorderSide(
color: AppColor.neonRed,
width: LayoutConstants.dimen_1,
style: BorderStyle.solid,
),
),
);
Catch in the above solution is that we are setting the size of the error message to 0.01 so as a result it don't show up.
Additionally we can have custom border for the error.
Note : Setting the Text size to 0 is not working as it don't consider the text size and textFormField widget gets shrinked.
The problem is that we are not able to see your code so it might be challenging to assist you but I will do everything from scratch. You can firstly create the authentication class in one dart file
class AuthBloc{
StreamController _passController = new StreamController();
Stream get passStream => _passController.stream;
bool isValid(String pass){
_passController.sink.add("");
if(pass == null || pass.length < 6){
_passController.sink.addError("Password is too short");
return false;
}
else{
return true;
}
}
void dispose(){
_passController.close();
}
}
And then insert the following code in another dart file...
class LoginPage extends StatefulWidget{
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage>{
AuthBloc authBloc = new AuthBloc();
#override
void dispose(){
authBloc.dispose();
}
#override
Widget build(BuildContext context){
return Scaffold(
body: Container(
padding: EdgeInsets.fromLTRB(30, 0, 30, 0),
constraints: BoxConstraints.expand(),
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(0, 40, 0, 20),
child: StreamBuilder(
stream: authBloc.passStream,
builder: (context, snapshot) => TextField(
controller: _passController,
style: TextStyle(fontSize: 18, color: Colors.black),
decoration: InputDecoration(
errorText: snapshot.hasError ? snapshot.error:null,
labelText: "Password",
prefixIcon: Container(
width: 50,
child: Icon(Icons.lock),
),
border: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xffCED802), width: 1),
borderRadius: BorderRadius.all(Radius.circular(6))
)
),
),
)
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 30, 0, 40),
child: SizedBox(
width: double.infinity,
height: 52,
child: RaisedButton(
onPressed: _onLoginClicked,
child: Text(
"Login",
style: TextStyle(fontSize: 18, color: Colors.white),
),
color: Color(0xff327708),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6))
),
),
),
),
]
)
)
}
_onLoginClicked(){
var isValid = authBloc.isValid(_passController.text);
if(isValid){
//insert your action
}
}
}
I hope it works :)
Instead of using a fixed height container to wrap the textFormField, You can try to put a space in the helper text so it will keep the height of the field constant while only displaying when there is an error.
return TextFormField(
// ...
decoration: InputDecoration(
// ...
helperText: " ",
helperStyle: <Your errorStyle>,
)
According to Flutter Doc :
To create a field whose height is fixed regardless of whether or not an error is displayed, either wrap the TextFormField in a fixed height parent like SizedBox, or set the InputDecoration.helperText parameter to a space.
The problem with content padding is that you cant decrease the size of the field to UI requirement with an emphasize on decrease but how ever the second answer helped me come with a solution for my perticular problem, so am sharing that
StreamBuilder(
stream: viewModel.outEmailError,
builder: (context, snap) {
return Container(
width: MediaQuery.of(context).size.width*.7,
height: (snap.hasData)?55:35,
child: AccountTextFormField(
"E-mail",
textInputType: TextInputType.emailAddress,
focusNode: viewModel.emailFocus,
controller: viewModel.emailController,
errorText: snap.data,
textCapitalization: TextCapitalization.none,
onFieldSubmitted: (_) {
nextFocus(viewModel.emailFocus,
viewModel.passwordFocus, context);
},
),
);
}),
I have a Row that has 3 fields in it: 2 TextFields, 1 DropdownButtonHideUnderline wrapped in a Container. I'm trying to ensure that the first TextField takes up about 50-60% and the other two fields share the remaining space. I also want the fields to have the same height. So, something like this:
This is the code I have:
#override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).accentColor,
child: Padding(
padding: const EdgeInsets.fromLTRB(5.0, 10.0, 5.0, 10.0),
child: Row(children: <Widget>[
Expanded(
child: Container(
padding: EdgeInsets.only(right: 5.0),
child: TypeAheadField(
textFieldConfiguration: TextFieldConfiguration(
autofocus: true,
controller: widget.ingredientController,
style: DefaultTextStyle.of(context)
.style
.copyWith(fontStyle: FontStyle.italic),
decoration: InputDecoration(
border: InputBorder.none,
filled: true,
fillColor: Colors.white.withOpacity(1),
hintText: 'Ingredient',
suffixIcon: GestureDetector(
onTap: widget.addFunction,
child: Icon(
Icons.add,
color: Colors.grey,
)))),
suggestionsCallback: (pattern) async {
return await _findIngredients(pattern);
},
//If not items are found, return an empty container.
noItemsFoundBuilder: (context) {
return Container(height: 0, width: 0);
},
itemBuilder: (context, suggestion) {
return ListTile(
title: Text(suggestion.name),
);
},
onSuggestionSelected: (Ingredient suggestion) {
widget.ingredientController.text = suggestion.name;
},
))),
Expanded(
child: TextField(
maxLines: 1,
controller: widget.quantityController,
keyboardType: TextInputType.text,
autofocus: false,
decoration: InputDecoration(
border: InputBorder.none,
filled: true,
fillColor: Colors.white.withOpacity(1),
hintText: 'Qty',
))),
Expanded(flex: 1, child: UnitDropdown()),
])));
}
What I'm left with is this:
I've tried setting the flex factor on the Expanded to different things, but that just results in an overflow on the right side. I've also not found a way to force all of the widgets to have the same height.
Try this one,
Row(children : <Widget>[
Expanded(
Container(child: TextField1())
),
Expanded(
Row(children : <Widget>[
Expanded(child: TextFiled2()),
Expanded(child: DropDown())
]);
)
]);
Or else, You can use MediaQuery to get the exact size of the screen.
Example:
Width : MediaQuery.of(context).size.width * 0.5;
Width : MediaQuery.of(context).size.width * 0.25;
Width : MediaQuery.of(context).size.width * 0.25;
Here you have, the key is to encapsulate the TextField, Dropdown, or whatever component you have in a Container, and define the actual size from the Container, tweaking the predefined internal Paddings of each widget (if you have the chance, sometimes is not available).
double itemsHeight = 30;
Widget getTextField({String hint = 'Ingredients', Widget suffix}) {
// use Container to define the size of the child,
// and reset the original inner paddings!
return Container(
height: itemsHeight,
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(color: Colors.white, width: 1)),
hintText: hint,
contentPadding: EdgeInsets.all(
0), // change each value, and set 0 remainding ones.
suffixIcon: suffix,
),
expands: false,
maxLines: 1,
controller: TextEditingController(),
),
);
}
return Scaffold(
body: Container(
color: Colors.green.withOpacity(.2),
margin: EdgeInsets.symmetric(vertical: 50, horizontal: 20),
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Flexible(
flex: 2,
child: getTextField(
hint: 'Ingredients',
suffix: Icon(
Icons.add,
size:
18, // option 1: reduce the size of the icon, and avoid the padding issues..
)),
),
Flexible(
flex: 1,
child: getTextField(
hint: 'Qty',
// option2: trick to match the expanded height of the icon on the previous field
// make an icon transparent :)
suffix: Icon(
Icons.account_box,
color: Colors.transparent,
)),
),
Flexible(
flex: 1,
child: Container(
// use this to match the Flex size..., is like using Expanded.
width: double.infinity,
// container defines the BoxConstrains of the children
decoration: BoxDecoration(
color: Colors.white24,
border: Border.all(color: Colors.white, width: 1),
),
height: itemsHeight,
child: DropdownButton(
hint: Text("Unit"),
onChanged: (i) {},
underline: Container(),
items: List.generate(5, (i) {
return DropdownMenuItem(child: Text("item $i"));
})),
),
),
],
),
),
);
screenshot of result: