I have a dropdown button as you can see below.
child: DropdownButton<String>(
value: dropDownValue,
icon: Icon(Icons.keyboard_arrow_down),
iconSize: 15,
elevation: 16,
style: TextStyle(color: Colors.grey),
underline: Container(
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
side: BorderSide(width: 1.0, style: BorderStyle.solid),
borderRadius: BorderRadius.all(Radius.circular(5.0)),
),
),
),
onChanged: (String newValue) {
setState(() {
dropDownValue = newValue;
});
},
items: [dropDownValue,...snapshot.data.data]
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value.name),
);
}).toList(),
),
I want to shape it like in the image by using decoration in Container, but i can't shape it the way i want
But right now this is the image I have. How do I add an edge to my dropdown button? Is there a known way for this?
You can copy paste run full code below
You can use DropdownButtonFormField with InputDecoration set fillColor and hintText
code snippet
DropdownButtonFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(30.0),
),
),
filled: true,
hintStyle: TextStyle(color: Colors.grey[800]),
hintText: "Name",
fillColor: Colors.blue[200]),
value: dropDownValue,
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String dropDownValue;
List<String> cityList = [
'Ajman',
'Al Ain',
'Dubai',
'Fujairah',
'Ras Al Khaimah',
'Sharjah',
'Umm Al Quwain'
];
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
void initState() {
//setFilters();
super.initState();
}
setFilters() {
setState(() {
dropDownValue = cityList[2];
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButtonFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(30.0),
),
),
filled: true,
hintStyle: TextStyle(color: Colors.grey[800]),
hintText: "Name",
fillColor: Colors.blue[200]),
value: dropDownValue,
onChanged: (String Value) {
setState(() {
dropDownValue = Value;
});
},
items: cityList
.map((cityTitle) => DropdownMenuItem(
value: cityTitle, child: Text("$cityTitle")))
.toList(),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
You can just wrap your DropdownButton widget into DecoratedBox :
return DecoratedBox(
decoration: ShapeDecoration(
color: Colors.cyan,
shape: RoundedRectangleBorder(
side: BorderSide(width: 1.0, style: BorderStyle.solid, color: Colors.cyan),
borderRadius: BorderRadius.all(Radius.circular(25.0)),
),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 0.0),
child: DropdownButton<String>(
value: dropdownValue,
icon: Icon(null),
elevation: 16,
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
underline: SizedBox(),
items: <String>['City', 'Country', 'State']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
);
Output :
Related
Anyone knows a fix for this i keep getting this error, I used an OnPressed here,
I think im suppose to use a VoidCallback here but when i use that i get the error:
"The argument type 'void Function(dynamic)' can't be assigned to the parameter type 'void Function()'."
Been stuck on this issue thanks for your help.
import 'package:concept1/constant.dart';
import 'package:concept1/screen/login/widget/welcome_back.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildAppBar(context),
body: Column(
children: [
const WelcomeBack(),
Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30),
child: Column(children: <Widget>[
InputTextField(
label: 'Email',
onChange: (value) {},
),
InputTextField(
label: 'Password',
onChange: (value) {},
),
]),
)
],
),
);
}
AppBar buildAppBar(BuildContext context) {
return AppBar(
backgroundColor: mBackgroundColor,
elevation: 0,
centerTitle: true,
title: Text(
'Login Screen',
style: TextStyle(
color: mPrimaryColor,
),
),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
color: mPrimaryColor,
onPressed: () {
Navigator.pop(context);
},
),
);
}
}
class InputTextField extends StatelessWidget {
const InputTextField({
Key? key,
required this.label,
required this.onChange,
}) : super(key: key);
final String label;
final Function? onChange;
#override
Widget build(BuildContext context) {
return TextField(
onChanged: onChange,
cursorColor: Colors.grey,
decoration: InputDecoration(
labelText: label,
labelStyle: const TextStyle(color: Colors.grey),
border: UnderlineInputBorder(
borderSide: BorderSide(
color: mPrimaryColor,
width: 2,
)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: mPrimaryColor,
width: 2,
)),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.grey,
width: 0.5,
))),
);
}
}
Whenever you pass a function as a argument you should use VoidCallBack instead of Function
Just change :
final Function? onChange
to
final VoidCallBack? onChange
I figured it out!
import 'package:concept1/constant.dart';
import 'package:concept1/screen/login/widget/welcome_back.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatelessWidget {
const LoginScreen({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: buildAppBar(context),
body: Column(
children: [
const WelcomeBack(),
Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30),
child: Column(children: <Widget>[
InputTextField(
label: 'Email',
onChange: () {},
),
InputTextField(
label: 'Password',
onChange: (() {}),
)
]),
)
],
),
);
}
AppBar buildAppBar(BuildContext context) {
return AppBar(
backgroundColor: mBackgroundColor,
elevation: 0,
centerTitle: true,
title: Text(
'Login Screen',
style: TextStyle(
color: mPrimaryColor,
),
),
leading: IconButton(
icon: const Icon(Icons.arrow_back_ios),
color: mPrimaryColor,
onPressed: () {
Navigator.pop(context);
},
),
);
}
}
class InputTextField extends StatelessWidget {
const InputTextField({
Key? key,
required this.label,
required this.onChange,
}) : super(key: key);
final String label;
final VoidCallback onChange;
#override
Widget build(BuildContext context) {
return TextField(
onChanged: (value) {},
cursorColor: Colors.grey,
decoration: InputDecoration(
labelText: label,
labelStyle: const TextStyle(color: Colors.grey),
border: UnderlineInputBorder(
borderSide: BorderSide(
color: mPrimaryColor,
width: 2,
)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: mPrimaryColor,
width: 2,
)),
enabledBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Colors.grey,
width: 0.5,
))),
);
}
}
I have a textformfield which validates min length to be at least 3 characters. Later on, I'll validate with backend that the username is unique.
But currently, I'm having trouble showing 2 error text for 2 errors. Namely, one for min length ( "Please enter at least 3 characters for your username") and one for non-unique username ('Your username is popular, please try another one.')
Questions:
How to make the suffix icon appear only when at least 1 character is typed? instead of by default, I know it's linked to hasMinLengthUnique = false.
How to show different error text for respective errors?
And later on, how to put a ternary operator on the navigation to another page based on value hasMinLengthUnique = true.
Bcos right now, whether hasMinLengthUnique = true or false, the navigation doesn't happen.
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.always,
child: TextFormField(
controller: _controller,
validator: (value) {
return (0 < value.length && value.length < 3)
? "Please enter at least 3 characters for your username"
: null;
},
onChanged: (value) {
setState(() {
value.length > 2
// && username must be unique
? hasMinLengthUnique = true
: hasMinLengthUnique = false;
});
},
style: TextStyle(color: Colors.white),
autofocus: true,
maxLength: 15,
decoration: InputDecoration(
suffix: hasMinLengthUnique
? IconButton(
icon:
Icon(Icons.check_circle, color: Colors.green))
: IconButton(
icon: Icon(Icons.cancel, color: Colors.red)),
errorBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 1.0),
),
errorStyle: TextStyle(color: Color(0xff4aa3f8)),
focusedErrorBorder: UnderlineInputBorder(
borderSide: BorderSide.none,
),
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15)),
// borderSide: BorderSide(width: 1, color: Colors.white),
),
),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.18,
),
Padding(
padding: EdgeInsets.only(
right: MediaQuery.of(context).size.height * 0.015,
),
child: DelayedDisplay(
delay: Duration(seconds: 3),
child: Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white,
primary: Color(0xff3a327f)),
child: Icon(Icons.chevron_right, size: 27),
onPressed: () async {
// if (formKey.currentState.validate()) {
Navigator.push(context, _createRoute());
// }
})),
))
]),
));
Here is the code
It checks whether a username is greater than 2 or not
Then it will check whether your username is popular or not (try typing admin)
It will update your hasMinLengthUnique accordingly that will update your UI of IconButton()
It will update your ElevatedButton() as well. It becomes disable if hasMinLengthUnique is false and become enable if hasMinLengthUnique is true.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool hasMinLengthUnique = false;
var _controller = TextEditingController();
GlobalKey<FormState> _formKey = GlobalKey();
var defUsername = ["admin"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Container(
color: Colors.lightBlue[900],
child: Column(
children: [
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.always,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _controller,
validator: (value) {
if (value.length < 3) {
return "Please enter at least 3 characters for your username";
}
if (value.contains(defUsername[0])) {
return "Username is too popular";
}
return null;
},
onChanged: (value) {
setState(() {
if (value.contains(defUsername[0]) ||
value.length <= 2) {
hasMinLengthUnique = false;
} else {
hasMinLengthUnique = true;
}
});
},
style: TextStyle(color: Colors.white),
autofocus: true,
maxLength: 15,
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(vertical: 0, horizontal: 10),
labelText: "Username",
suffix: hasMinLengthUnique
? Icon(Icons.check_circle, color: Colors.green)
: _controller.text.isEmpty
? Icon(null, color: Colors.red)
: Icon(Icons.cancel, color: Colors.red),
border: OutlineInputBorder(),
),
),
),
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.18,
),
Padding(
padding: EdgeInsets.only(
right: MediaQuery.of(context).size.height * 0.015,
),
child: Container(
child: Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
onPrimary: Colors.white, primary: Color(0xff3a327f)),
child: Icon(Icons.chevron_right, size: 27),
onPressed: hasMinLengthUnique
? () {
print("go to next screen");
}
: null,
),
),
),
)
],
),
),
),
);
}
}
Thank you!
Have you tried if else statement in onChanged Value
var isValidate;
onChanged(){
if(1st condition){
setState(){}
}
else if(2nd condition){
setState(){}
}
}
I'm developing an application on flutter and I'm having a problem with the position of the ElevatedButton. When the Validator returns the error message below the TextFormField, the widget expands downward and the position of the add button changes. I would like to keep the add button pinned to the same position as the beginning of the app
button in normal position
Button out of its original position after returning the validator
My code:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Lista de Compras"),
backgroundColor: Colors.green,
centerTitle: true,
),
body: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(15, 10, 5, 10),
child: Form(
key: _formKey,
child: Row(
children: <Widget>[
Theme(
data: ThemeData(
primaryColor: Colors.green,
hintColor: Colors.green),
child: Expanded(
child: TextFormField(
controller: _controlador,
validator: (value) {
if (value.isEmpty) {
return "Insira um item";
}
return null;
},
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green),
borderRadius:
BorderRadius.circular(100)),
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(100)),
labelText: "Novo item",
hintText: "Insira um item",
hintStyle: TextStyle(color: Colors.grey),
labelStyle:
TextStyle(color: Colors.green),
suffixIcon: IconButton(
onPressed: () => _controlador.clear(),
icon: Icon(Icons.clear,
color: Colors.grey),
))))),
Padding(padding: EdgeInsets.only(right: 6)),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.green,
shape: CircleBorder(),
padding: EdgeInsets.all(12)),
child: Icon(Icons.add, color: Colors.white),
onPressed: () {
if (_formKey.currentState.validate()) {
_addCompras();
}
}),
],
),
)),
This is an expected behaviour, when TextFormField show an errorText this will append a text below the TextFormField adding extra height for about 22. Check working example below :
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light(),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
children: [
MeasureSize(
child: FormWidget(),
onChange: (size) {
print(size);
},
),
MeasureSize(
child: FormWidget(hideError: false),
onChange: (size) {
print(size);
},
),
FormWidget(
hideError: false,
addPaddingToTrailingButton: true,
),
],
),
),
);
}
}
class FormWidget extends StatelessWidget {
final bool hideError;
final bool addPaddingToTrailingButton;
FormWidget({
this.hideError = true,
this.addPaddingToTrailingButton = false,
});
#override
Widget build(BuildContext context) {
Widget trailingButton = ElevatedButton(
style: ElevatedButton.styleFrom(
shape: CircleBorder(),
padding: EdgeInsets.all(12),
),
child: Icon(Icons.add),
onPressed: () {},
);
if (addPaddingToTrailingButton) {
trailingButton = Padding(
padding: const EdgeInsets.only(bottom: 22),
child: trailingButton,
);
}
return Container(
color: Colors.grey[300],
margin: const EdgeInsets.symmetric(vertical: 16),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 8),
Expanded(
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100),
),
labelText: "Label text field",
hintText: "Hint text field",
errorText: hideError ? null : 'Error text shown',
suffixIcon: IconButton(
onPressed: () {},
icon: Icon(Icons.clear),
),
),
),
),
SizedBox(width: 8),
trailingButton,
],
),
);
}
}
typedef void OnWidgetSizeChange(Size size);
class MeasureSizeRenderObject extends RenderProxyBox {
Size oldSize;
final OnWidgetSizeChange onChange;
MeasureSizeRenderObject(this.onChange);
#override
void performLayout() {
super.performLayout();
Size newSize = child.size;
if (oldSize == newSize) return;
oldSize = newSize;
WidgetsBinding.instance.addPostFrameCallback((_) {
onChange(newSize);
});
}
}
class MeasureSize extends SingleChildRenderObjectWidget {
final OnWidgetSizeChange onChange;
const MeasureSize({
Key key,
#required this.onChange,
#required Widget child,
}) : super(key: key, child: child);
#override
RenderObject createRenderObject(BuildContext context) {
return MeasureSizeRenderObject(onChange);
}
}
I have adding a background so it will show the height difference :
TextField without errorText shown.
TextField with errorText shown.
TextField with errorText shown, with additional padding on icon button.
Check dartpad here
the answer by Allan above is very great.
But if you are facing issues learning that do it this way:
Add Elevated button to Column and add SizedBox with height 22 as its children. Here the height is calculated as (Height of TextFormField with error - of TextFormField without error) using flutter inspector.
Column(
children: [
ElevatedButton(...),
SizedBox(
height: 22,
),
],
),
Now add helperText: ' ', in TextFormField InputDecoration:
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return "Insira um item";
}
return null;
},
decoration: InputDecoration(
helperText: ' ',
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(100)),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(100)),
labelText: "Novo item",
hintText: "Insira um item",
hintStyle: TextStyle(color: Colors.grey),
labelStyle: TextStyle(color: Colors.green),
),
),
Here you can see the dartpad for full code.
This will get you this result:
How can I create a search similar to the one used by Whatsapp in its appBar but at the body.
It's a title on the left and the magnifying glass icon on the right. When you click on the icon, a search input opens on top of the title.
Updated answer
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _showSearch = false;
FocusNode _focusNode;
Widget _searchBar() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: _showSearch
? Row(
children: [
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
setState(() {
_showSearch = false;
FocusScope.of(context).unfocus();
});
},
),
Expanded(
child: TextField(
focusNode: _focusNode,
autofocus: true,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
hintText: 'Filtro',
hintStyle: TextStyle(
color: Colors.white,
),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
),
),
],
)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'WhatsApp',
),
IconButton(
icon: Icon(
Icons.search,
),
onPressed: () {
setState(() {
_showSearch = true;
FocusScope.of(context).requestFocus(_focusNode);
});
},
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Search'),
),
body: Container(
color: Colors.grey[300],
padding: const EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
height: 100,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: 50,
alignment: Alignment.center,
child: Text(
'Tab view here',
),
),
_searchBar(),
],
),
),
Expanded(
child: ListView(
padding: const EdgeInsets.all(5),
children: [
ListTile(
title: Text('Tile 1'),
subtitle: Text('Content'),
),
ListTile(
title: Text('Tile 2'),
subtitle: Text('Content'),
),
],
),
),
],
),
),
);
}
}
Old answer
Do you mean like this?
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _showSearch = false;
FocusNode _focusNode;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: _showSearch
? IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
setState(() {
_showSearch = false;
FocusScope.of(context).unfocus();
});
},
)
: null,
title: _showSearch
? TextField(
focusNode: _focusNode,
autofocus: true,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
hintText: 'Search...',
hintStyle: TextStyle(
color: Colors.white,
),
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
disabledBorder: InputBorder.none,
),
)
: Text('WhatsApp'),
actions: _showSearch
? []
: [
IconButton(
icon: Icon(
Icons.search,
color: Colors.white,
),
onPressed: () {
setState(() {
_showSearch = true;
FocusScope.of(context).requestFocus(_focusNode);
});
},
),
IconButton(
icon: Icon(
Icons.more_vert,
color: Colors.white,
),
),
],
),
body: Center(
child: Text('Content'),
),
);
}
}
Hi i got stuck while write flutter code on dropdown button, where after user choosed from the list the hint wont changed to what the user choose. Can anyone help ?
So here is my code:
DropdownButton(items: [
DropdownMenuItem(value: "1", child: Text('+')),
DropdownMenuItem(value: "2", child: Text('-')),
DropdownMenuItem(value: "3", child: Text('X')),
DropdownMenuItem(value: "4", child: Text('/'))
].toList(), onChanged: (value){
setState(() {
_value = value;
});
},hint: Text('Operation'),)
I have just created an example below just check it and let me know if it works :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String selectedOperator;
var listOfOperators = [
Operators(type: "+ Addition", value: 1),
Operators(type: "- Substraction", value: 2),
Operators(type: "* Multiplication", value: 3),
Operators(type: "/ Division", value: 4),
];
#override
void initState() {
super.initState();
print(listOfOperators.length);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Container(
child: Padding(
padding: const EdgeInsets.all(30.0),
child: Container(
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
border: Border.all(
color: Colors.red, style: BorderStyle.solid, width: 0.80),
),
child: DropdownButton(
value: selectedOperator,
isExpanded: true,
icon: Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Icon(Icons.arrow_drop_down),
),
iconSize: 25,
underline: SizedBox(),
onChanged: (newValue) {
setState(() {
print(newValue);
selectedOperator = newValue;
});
print(selectedOperator);
},
hint: Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Select'),
),
items: listOfOperators.map((data) {
return DropdownMenuItem(
value: data.value.toString(),
child: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Text(
data.type,
style: TextStyle(
fontSize: 18,
color: Colors.black,
),
),
),
);
}).toList()),
),
),
),
),
),
);
}
}
class Operators {
String type;
int value;
Operators({this.type, this.value});
}
Here you go with running example:
String dropdownValue = 'Lahore';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.deepPurple
),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>['Lahore', 'Islamabad', 'Faisalabad', 'Attabad']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.toList(),
);
}