Creating a custom drop down menu flutter - flutter

I am trying to create a custom drop down menu for my app, I have a picture of what it should look like. I have been searching online to see if there are any similar ideas, although everything I'm finding does not support null safety and so I am running into problems. If it comes down to it I will try and code my own drop down although if anyone could lead me in the right direction that would be great only because I'm new to flutter.
Also I have tried using DropdownButton in flutter but it does not produce what I am looking for.

Use DropDown button class, here is a complete running code, you can run it in dartpad
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
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(),
),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
String dropdownValue = 'One';
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
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(),
);
}
}

You can achieve that using DropdownButton2.
Check out Example 3 of How to add different height items like dividers and check out Options to see all parameters you can use to customize DropdownButton2 to your design.
Disclaimer: I am the author of the package mentioned above.

Related

flutter DropDownButton remove arrow icon?

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(),
);
}
}

How to change CheckboxListTile height?

Shortly, I need the selectable area to be smaller in terms of height.
Text and Checkbox sizes are good, but the surrounding box is too big for the checklist I'm trying to create.
CheckBoxListTile current height vs. desired height
Tried wrapping it with Transform.scale but text becomes too small:
Transform.scale(
scale: 0.8,
child: CheckboxListTile(
title: const Text("Rinite alérgica"),
value: timeDilation != 1.0,
controlAffinity: ListTileControlAffinity.leading,
onChanged: (bool value) {
setState(() {
timeDilation = value ? 2.0 : 1.0;
});
},
),
),
Tried wrapping it with Container, but I get on-screen overflow warnings.
Does anyone have a better solution?
When trying to resize the CheckboxListFile it seems that Google actually recommends creating a custom Tile widget and making use of the Checkbox widget.
https://api.flutter.dev/flutter/material/CheckboxListTile-class.html#material.CheckboxListTile.3
Look at the LabeledCheckbox widget that's been created. You can very easily modify all components to fit your needs. For example, if you wished to make the Widget itself smaller, you can now wrap it in a Container
/// Flutter code sample for CheckboxListTile
// ![Custom checkbox list tile sample](https://flutter.github.io/assets-for-api-docs/assets/material/checkbox_list_tile_custom.png)
//
// Here is an example of a custom LabeledCheckbox widget, but you can easily
// make your own configurable widget.
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(),
),
),
);
}
}
class LabeledCheckbox extends StatelessWidget {
const LabeledCheckbox({
Key key,
#required this.label,
#required this.padding,
#required this.value,
#required this.onChanged,
}) : super(key: key);
final String label;
final EdgeInsets padding;
final bool value;
final Function onChanged;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
onChanged(!value);
},
child: Container(
padding: padding,
child: Row(
children: <Widget>[
Expanded(child: Text(label)),
Checkbox(
value: value,
onChanged: (bool newValue) {
onChanged(newValue);
},
),
],
),
),
);
}
}
/// 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> {
bool _isSelected = false;
#override
Widget build(BuildContext context) {
return LabeledCheckbox(
label: 'This is the label text',
padding: const EdgeInsets.symmetric(horizontal: 20.0),
value: _isSelected,
onChanged: (bool newValue) {
setState(() {
_isSelected = newValue;
});
},
);
}
}
Have you tried ?
SizedBox(
height: 50,
width: 50,
child: ......
)

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.

Hide keyboard upon tapping on radio button in Flutter

I am trying to find a way to dismiss the keyboard upon tapping on the radio buttons. I found some answers like this tutorial (https://flutterigniter.com/dismiss-keyboard-form-lose-focus/) but this will only hide the keyboard upon clicking outside the text field on an empty spot not tapping the radio button.
Here is a simple code if you would like to try. Any thoughts will be highly appreciated. Thanks
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
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(),
),
),
);
}
}
enum SingingCharacter { lafayette, jefferson }
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
SingingCharacter _character = SingingCharacter.lafayette;
Widget build(BuildContext context) {
return Column(
children: <Widget>[
TextField(
autofocus: true,
),
ListTile(
title: const Text('Lafayette'),
leading: Radio(
value: SingingCharacter.lafayette,
groupValue: _character,
onChanged: (SingingCharacter value) {
setState(() {
_character = value;
});
},
),
),
ListTile(
title: const Text('Thomas Jefferson'),
leading: Radio(
value: SingingCharacter.jefferson,
groupValue: _character,
onChanged: (SingingCharacter value) {
setState(() {
_character = value;
});
},
),
),
],
);
}
}
in onChange Function write this line of code FocusScope.of(context).unfocus();
A couple of Solutions
Using SystemChannels
import 'package:flutter/services.dart';
SystemChannels.textInput.invokeMethod('TextInput.hide');
Using FocusScope
FocusScope.of(context).unfocus();
Add this line in onChange Function
FocusScope.of(context).requestFocus(new FocusNode());

How to update child dropdown after parent dropdown's selection changes?

So I have a column of dropdowns, each dropdown a prerequisite of the dropdown below. When Dropdown A changes its value, I'd make an API call and populate Dropdown B, Dropdown C's options are dependent on the value of B, and so on...
I accomplished this scenario fine, but the problem I'm having is when Dropdowns A to D have been selected, and I change the value of Dropdown B, Dropdowns C and D doesn't change its value.
SOS & TY
Refer the given example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This is the main application widget.
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(),
),
),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
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 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>['One', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}