flutter DropDownButton remove arrow icon? - flutter

I have a simple DropDownButton and would like to disable/hide the downward pointing arrow that is attached to it but there doesn't seem to be an option for it?
A very hacky workaround is to set a custom icon and give it a transparent color but that really does not feel like a good solution.

add iconSize: 0.0 to your DropdownButton like this
DropdownButton(
iconSize: 0.0,
...
)

Make use of the Visibility widget like this -
icon: Visibility (visible:false, child: Icon(Icons.arrow_downward)),
See the complete code below:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Visibility (visible:false, child: Icon(Icons.arrow_downward)),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}

The best way is to defined an empty Widget as icon.
An empty Widget can be set with SizedBox.shrink(), so you need to add icon: SizedBox.shrink(), to your DropdownButton parameters.
Here a quick example :
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
elevation: 16,
icon: SizedBox.shrink(),
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}

Related

How to draw a border around DropdownButton like the TextFormField border?

There are many answers on StackOverflow that explain how to draw a border around a widget. However, I am looking for something like TextFormField.
The normal DropdownButton has an underline attribute only but I am looking for something like the following design:
As you can see here, the dropdown list has a border and a title.
I can remove the underline attribute from the DropdownButton widget but is there any custom widget that I can use in order to wrap the DropdownButton?
You can replicate this with PopupMenuButton or Wrap it under InputDecorator then hide underline with DropdownButtonHideUnderline
/// Flutter code sample for DropdownButton
// This sample shows a `DropdownButton` with a large arrow icon,
// purple text style, and bold purple underline, whose value is one of "One",
// "Two", "Free", or "Four".
//
// ![](https://flutter.github.io/assets-for-api-docs/assets/material/dropdown_button.png)
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatefulWidget(),
),
),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return InputDecorator(
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(
horizontal: 20.0, vertical: 15.0),
labelText: 'Label',
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(5.0)),
),
child: DropdownButtonHideUnderline( child:DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_drop_down),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
), ),
);
}
}
I didn't know there is another widget specifically created to be used in the form. DropdownButtonFormField is the widget and it doesn't need all the extra lines mentioned by #flakerimi.
This is my sample code for those who want to look at.
DropdownButtonFormField<String>(
validator: (value) =>
dropdownValue == null ? S.of(context).general_make_selection : null,
autovalidateMode: AutovalidateMode.onUserInteraction,
value: dropdownValue,
decoration: InputDecoration(
labelText: S.of(context).bill_obj_type,
filled: true,
),
icon: const Icon(Icons.arrow_drop_down),
iconSize: 24,
elevation: 16,
isExpanded: true,
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(color: AppColors.neutral1),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
vm.objectionType = newValue;
});
},
items: _getDropdownMenuItems(),
);

Flutter: Get data back from StatefulWidget child class to parent

I'm new to flutter.
I have a page (Stateful Widget) in the app with a lot of widgets in a column. To improve the code readability, I took some widgets, and made them into seperate classes. For example, I made my dropdownmenu widget, into its only class, like this:
class DropDownMenuWidget extends StatefulWidget {
DropDownMenuWidget({Key? key}) : super(key: key);
#override
_DropDownMenuWidgetState createState() => _DropDownMenuWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _DropDownMenuWidgetState extends State<DropDownMenuWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (String? newValue) {
setState(() {
dropdownValue = newValue!;
});
},
items: MASLULIM
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
Now, in the parent class, I display the widget like this:
DropDownMenuWidget(),
However, the problem is, when the user clicks on a item, I can only retrieve that value from the DropDownMenu class, and there the setState() method is called. However, I need to read this value in the parent class. How can I get it there?
Thanks
Instead of creating your dropdownValue variable in your Widget, you can get it from the parent Widget as following with the help of ValueNotifier
class DropDownMenuWidget extends StatefulWidget {
ValueNotifier dropdownValueNotifier;
DropDownMenuWidget(this.dropdownValueNotifier, {Key key}) : super(key: key);
#override
_DropDownMenuWidgetState createState() => _DropDownMenuWidgetState();
}
class _DropDownMenuWidgetState extends State<DropDownMenuWidget> {
#override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: widget.dropdownValueNotifier,
builder: (context, dropdownValue, _) {
return DropdownButton<String>(
value: dropdownValue,
// ...
onChanged: (String newValue) {
// simply change the value. You dont need setState anymore
widget.dropdownValueNotifier.value = newValue;
},
// ...
);
},
);
}
}
In the parent Widget, create the variable and pass it like this
ValueNotifier dropdownValueNotifier = ValueNotifier('One');
// ...
DropDownMenuWidget(dropdownValueNotifier),
In this case, you can use typedef
First in a separate DrobDown menu you can create the following icon outside of the class:
typedef OnItemSelectedDropDown = Function (String value);
Now you can apply this thing as follows :
class DropDownMenuWidget extends StatefulWidget {
final OnItemSelectedDropDown onItemSelected ;
DropDownMenuWidget({Key? key}) : super(key: key);
#override
_DropDownMenuWidgetState createState() => _DropDownMenuWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _DropDownMenuWidgetState extends State<DropDownMenuWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(
color: Colors.black,
fontSize: 20,
),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (String value) {
//This line return Value
widget.onItemSelected.call(value);
},
items: MASLULIM
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
When calling the class DropDownMenuWidget, it is called as follows on another screen:
String dropdownValue ;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('DropDown Page'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'New Value DropDown : $dropdownValue',
),
DropDownMenuWidget(
onItemSelected :(newValue){
setState(() {
dropdownValue = newValue ;
});
}
),
],
),
),
);
}

How to adjust the height and width of a dropdown list in flutter (I've given the code, just tell me how to adjust that)

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 15,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
You can add width: (specification) and height: (specification) in your dropdown list. Specification -> number.
Please, use the Code Sample formatting option.
you can do it like this :
return Container(
child: DropdownButton(
value: dropdownValue,
icon: Icon(Icons.arrow_downward),
iconSize: 15,
elevation: 16,
style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (newValue) {
setState(() {
dropdownValue = newValue;
});
},
items: ['One', 'Two', 'Free', 'Four'] .map<DropdownMenuItem>((String value) {
return DropdownMenuItem(
value: value,
child: Container(
height: 100,
width: 200,
alignment: Alignment.centerLeft,
child: Text(value)
)
);
}).toList(),
)
);
Btw, please use the Code Sample formatting option.

DropdownButton doesn't re-render the menu when items change

DropdownButton doesn't reflect menuItem's changes when the dropdown menu is open.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: Center(
child: MyStatefulWidget(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
final disabledItems = ['Free', 'Four'];
List<String> items = ['One', 'Two', 'Free', 'Four'];
String dropdownValue = 'One';
#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) {
if (!disabledItems.contains(newValue)) {
setState(() {
dropdownValue = newValue;
});
}
},
items: items.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Row(children: [
Text(
value,
style: TextStyle(
color: disabledItems.contains(value) ? Colors.grey : null,
),
),
IconButton(
icon: Icon(Icons.delete),
color: Colors.black38,
onPressed: () {
setState(() {
items.removeWhere((element) => element == 'Two');
});
print(items.length);
},
)
]),
);
}).toList(),
);
}
}
What I aim is the chance of removing an item from the menu when the delete icon is pressed. All the expected events are working as expected and the DropDown items list is updating accordingly in the backend but it doesn't re-render.
DorpDown Menu with delete icon
In order to be able to see the updated items list I have to close the dropdown menu and open it again but this doesn’t feel right in terms of user experience.

How do I clear a Flutter DropdownButton programmatically?

I have two dropdown buttons that are mutually exclusive. How can I clear (or set) the value of one when the other is set?
Thanks
for 1st dropdown:
onChanged: (String newValue) {
setState(() {
dropdownValueFirst = newValue;
dropdownValueSecond = "Bangladesh";
});
},
for 2nd dropdown:
onChanged: (String newValue) {
setState(() {
dropdownValueSecond = newValue;
dropdownValueFirst ="One";
});
},
See below code:
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#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);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String dropdownValueFirst="One";
String dropdownValueSecond="Bangladesh";
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
DropdownButton<String>(
value: dropdownValueFirst,
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(() {
dropdownValueFirst = newValue;
dropdownValueSecond = "Bangladesh";
});
},
items: <String>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.toList(),
),
const Padding(padding: EdgeInsets.only(left: 8)),
DropdownButton<String>(
value: dropdownValueSecond,
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(() {
dropdownValueSecond = newValue;
dropdownValueFirst ="One";
});
},
items: <String>['Bangladesh', 'India', 'China']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
})
.toList(),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
When 1st drop down in pressed then try to reset value of 2nd dropdown inside setState on onChanged event and vice versa,
onChanged: (String newValue) {
setState(() {
dropdownValueFirst = newValue;
dropdownValueSecond='Initial Value of second',// remeber this value must be same as initial value of 2nd dropdown =>value: 'Initial Value of second',
});
},