Problem statement
By default dropdown menu items open on top of the dropdown button, and when we get a design showing dropdown menu items listed under the dropdown button, somehow the developer has to figure out how to achieve it.
How I achieved it
we will be using Flutter is one of the well-matured cross-platform app development frameworks out there and we can build pixel-perfect apps from it.
I will be using vscode as my code editor, let's create a flutter project,
open pubspec.yaml and add this package dropdown_button2
with this package, we can design dropdown button and menu UI however we want.
so in this article, we are focusing only on opening menu items under the dropdown button.
Let's open main.dart delete all unwanted code, add default DropdownButton() widget with items and also add DropdownButton2() into Column.
I'm using Faker package to generate menu items
magic happens in these lines of code
dropdownStyleData: DropdownStyleData(
maxHeight: MediaQuery.of(context).size.height * 0.3),
here I'm giving 30% of the screen size because I placed dropdown buttons in the center of the screen so it will work here but if you want to place dropdown button in different place of the screen then you have to changes maxHeight value based on your UI
default dropdown widget
menu items under dropdown button
here is the full code.
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:faker/faker.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dropdown menu items',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Dropdown menu items'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> getNamesList(int length) {
return List.generate(length, (index) => Faker().food.dish())
.toSet()
.toList();
}
List<DropdownMenuItem<String>> getItems(List<String> list) {
return list.map((e) => DropdownMenuItem(value: e, child: Text(e))).toList();
}
Widget get getHintWidget => Text('Select Item',
style: TextStyle(fontSize: 14, color: Theme.of(context).hintColor));
List<String>? list1;
List<String>? list2;
String? value1;
String? value2;
@override
void initState() {
list1 = getNamesList(40);
list2 = getNamesList(40);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("default dropdown button"),
DropdownButtonHideUnderline(
child: DropdownButton(
value: value1,
onChanged: (value) {
value1 = value;
setState(() {});
},
hint: getHintWidget,
items: getItems(list1!),
),
),
const Text("open under button"),
DropdownButtonHideUnderline(
child: DropdownButton2<String>(
hint: getHintWidget,
items: getItems(list2!),
value: value2,
onChanged: (value) {
value2 = value;
setState(() {});
},
dropdownStyleData: DropdownStyleData(
maxHeight: MediaQuery.of(context).size.height * 0.3),
),
),
],
),
),
);
}
}
Thank you happy coding...
Top comments (0)