Flutter下拉菜单覆盖层插件dropdown_overlay的使用
Flutter下拉菜单覆盖层插件dropdown_overlay
的使用
标题
Flutter下拉菜单覆盖层插件dropdown_overlay
的使用
内容
-
简介
dropdown_overlay
是一个提供简单方式创建自定义下拉菜单的Flutter包。
-
功能
- 只支持单选下拉菜单
- 支持搜索和可选下拉菜单
- 支持下拉菜单定制
- 精确对齐下拉菜单与触发器通过
DropdownMenuPosition
- 使用
SimpleDropdown.custom
自定义下拉菜单
- 精确对齐下拉菜单与触发器通过
- 控制下拉菜单程序化管理通过
DropdownController
- 由控制器管理选择项,共享状态跨组件/页面
- 搜索下拉菜单
- 同步/异步加载项目通过
DropdownController
-
开始使用
import 'package:dropdown_overlay/dropdown_overlay.dart';
-
示例代码
import 'package:flutter/material.dart';
import 'package:dropdown_overlay/dropdown_overlay.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Simple Dropdown Example'),
),
body: const Center(
child: DropdownExample(),
),
),
);
}
}
class DropdownExample extends StatefulWidget {
const DropdownExample({super.key});
[@override](/user/override)
State<DropdownExample> createState() => _DropdownExampleState();
}
class _DropdownExampleState extends State<DropdownExample> {
final _singleSelectionController = DropdownController<String>.single(
items: List.generate(15, (index) => DropdownItem(value: "Single $index")),
);
final _multiSelectionController = DropdownController<String>.multi(
items: List.generate(15, (index) => DropdownItem(value: "Multi $index")),
);
final TextEditingController _singleSearch = TextEditingController();
final TextEditingController _multiSearch = TextEditingController();
[@override](/user/override)
void dispose() {
_singleSelectionController.dispose();
_multiSelectionController.dispose();
_singleSearch.dispose();
_multiSearch.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
const SizedBox(height: 30),
SimpleDropdown<String>.list(
controller: _singleSelectionController,
builder: (_) => Container(
width: 150,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(4),
),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("Single Select"),
SizedBox(width: 8),
Icon(Icons.arrow_drop_down),
],
),
),
menuPosition: const DropdownMenuPosition(
offset: Offset(0, 10),
),
menuConstraints: const BoxConstraints(
maxHeight: 150,
),
itemBuilder: (_, item) => GestureDetector(
onTap: () {
_singleSelectionController.select(item.value, dismiss: false);
},
child: Card(
color: item.selected ? Colors.green : Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(item.value),
),
),
),
),
const SizedBox(height: 50),
SimpleDropdown<String>.list(
controller: _multiSelectionController,
builder: (_) => Container(
width: 150,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(4),
),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("Multi Select"),
SizedBox(width: 8),
Icon(Icons.arrow_drop_down),
],
),
),
menuPosition: const DropdownMenuPosition(
offset: Offset(0, 5),
),
menuConstraints: const BoxConstraints(
maxHeight: 150,
),
itemBuilder: (_, item) => GestureDetector(
onTap: () {
_multiSelectionController.select(item.value, dismiss: false);
},
child: Card(
color: item.selected ? Colors.green : Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(item.value),
),
),
),
),
const SizedBox(height: 50),
const Divider(),
const SizedBox(height: 50),
SimpleDropdown<String>.list(
controller: _singleSearchController,
builder: (_) => SizedBox(
width: 1150,
child: TextField(
controller: _singleSearch,
decoration: const InputDecoration(
labelText: "Single Search",
border: OutlineInputBorder(),
),
onChanged: (value) {
if (!_singleSearchController.isOpen) {
_singleSearchController.open();
}
if (value.isEmpty) {
_singleSearchController.restore();
} else {
_singleSearchController.search(
value,
matcher: (query, item) => item.contains(query),
);
}
},
),
),
menuPosition: const DropdownMenuPosition(
offset: Offset(0, 5),
),
menuConstraints: const BoxConstraints(
maxHeight: 150,
),
itemBuilder: (_, item) => GestureDetector(
onTap: () {
_singleSearchController.select(item.value, dismiss: false);
},
child: Card(
color: item.selected ? Colors.green : Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(item.value),
),
),
),
),
const SizedBox(height: 50),
SimpleDropdown<String>.list(
controller: _multiSearchController,
builder: (_) => SizedBox(
width: 150,
child: TextField(
controller: _multiSearch,
decoration: const InputDecoration(
labelText: "Multi Search",
border: OutlineInputBorder(),
),
onChanged: (value) {
if (!_multiSearchController.isOpen) {
_multiSearchController.open();
}
if (value.isEmpty) {
_multiSearchController.restore();
} else {
_multiSearchController.search(
value,
matcher: (query, item) => item.contains(query),
);
}
},
),
),
menuPosition: const DropdownMenuPosition(
targetAnchor: Alignment.topLeft,
anchor: Alignment.bottomLeft,
offset: Offset(0, -5),
),
menuConstraints: const BoxConstraints(
maxHeight: 1150,
),
itemBuilder: (_, item) => GestureDetector(
onTap: () {
_multiSearchController.select(item.value, dismiss: false);
},
child: Card(
color: item.selected ? Colors.green : Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(item.value),
),
),
),
),
const SizedBox(height: 50),
TextButton(
onPressed: () {
_multiSearchController.load(
() => List.generate(
5,
(index) => DropdownItem(value: "Load More $index"),
),
);
},
style: TextButton.styleFrom(
backgroundColor: Colors.green,
side: const BorderSide(color: Colors.grey),
),
child: const Text("Load More"),
),
],
),
);
}
}
更多关于Flutter下拉菜单覆盖层插件dropdown_overlay的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter下拉菜单覆盖层插件dropdown_overlay的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用dropdown_overlay
插件来实现下拉菜单覆盖层的示例代码。这个插件允许你自定义下拉菜单的样式和行为。首先,确保你已经在pubspec.yaml
文件中添加了dropdown_overlay
依赖:
dependencies:
flutter:
sdk: flutter
dropdown_overlay: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,这里有一个完整的示例代码,展示了如何使用dropdown_overlay
:
import 'package:flutter/material.dart';
import 'package:dropdown_overlay/dropdown_overlay.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Dropdown Overlay Example'),
),
body: Center(
child: MyDropdownOverlay(),
),
),
);
}
}
class MyDropdownOverlay extends StatefulWidget {
@override
_MyDropdownOverlayState createState() => _MyDropdownOverlayState();
}
class _MyDropdownOverlayState extends State<MyDropdownOverlay> {
final List<String> items = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
String? selectedItem;
@override
Widget build(BuildContext context) {
return DropdownOverlay(
// Customize the overlay configuration
overlayConfiguration: OverlayConfiguration(
alignment: Alignment.topLeft,
margin: EdgeInsets.only(top: 20),
padding: EdgeInsets.all(8),
borderRadius: BorderRadius.circular(10),
backgroundColor: Colors.white,
elevation: 4,
shadowColor: Colors.black.withOpacity(0.2),
shadowBlurRadius: 10,
),
child: DropdownButton<String>(
value: selectedItem,
hint: Text('Select an item'),
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(() {
selectedItem = newValue;
});
},
items: items.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
);
}
}
在这个示例中,我们做了以下几件事:
- 引入依赖:首先确保
dropdown_overlay
依赖已经添加到项目中。 - 定义UI结构:使用
DropdownOverlay
包裹DropdownButton
。 - 配置覆盖层:通过
overlayConfiguration
属性自定义下拉菜单覆盖层的样式,比如对齐方式、边距、内边距、圆角、背景颜色、阴影等。 - 处理选项变化:在
onChanged
回调中更新选中的值。
这个示例展示了如何使用dropdown_overlay
插件来自定义下拉菜单的样式,使其更符合你的应用需求。你可以根据实际需求进一步调整覆盖层的配置。