Flutter弹出菜单插件app_popup_menu的使用
Flutter弹出菜单插件app_popup_menu的使用
app_popup_menu
是一个增强版的Flutter弹出菜单插件,旨在提供更动态和适应性更强的菜单选项。本文将介绍如何安装和使用这个插件,并提供一个完整的示例demo。
安装
首先,在你的 pubspec.yaml
文件中添加 app_popup_menu
依赖:
dependencies:
app_popup_menu: ^1.0.0
注意:始终使用主要版本号(如 1.0.0
),这样可以自动获取次要版本中的新功能和补丁版本中的修复。
示例代码
以下是一个完整的示例demo,展示如何在Flutter应用中使用 app_popup_menu
插件。
main.dart
import 'package:flutter/material.dart';
import 'package:app_popup_menu/app_popup_menu.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: BuildInheritedWidget(child: HomeScreen()),
);
}
}
class BuildInheritedWidget extends StatefulWidget {
final Widget child;
BuildInheritedWidget({required this.child});
@override
_BuildInheritedWidgetState createState() => _BuildInheritedWidgetState();
}
class _BuildInheritedWidgetState extends State<BuildInheritedWidget> {
String data = '';
@override
Widget build(BuildContext context) {
return InheritedData(
data: data,
child: widget.child,
);
}
}
class InheritedData extends InheritedWidget {
final String data;
InheritedData({required this.data, required Widget child})
: super(child: child);
static InheritedData? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<InheritedData>();
}
@override
bool updateShouldNotify(InheritedData oldWidget) {
return data != oldWidget.data;
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late AppPopupMenu<String> appMenu01;
late AppPopupMenu<int> appMenu02;
late AppPopupMenu<String> appMenu03;
@override
void initState() {
super.initState();
appMenu01 = AppPopupMenu<String>(
items: ['Option 1', 'Option 2', 'Option 3'],
initialValue: 'Option 3',
onSelected: (String value) {
InheritedData.of(context)?.data = value;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('appMenu01 option: $value')),
);
},
tooltip: "Here's a tip for you.",
elevation: 8,
icon: const Icon(Icons.settings),
offset: const Offset(0, 45),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
);
appMenu02 = AppPopupMenu<int>(
menuItems: const [
PopupMenuItem(value: 1, child: Text('First')),
PopupMenuItem(value: 2, child: Text('Second')),
],
initialValue: 2,
onSelected: (int value) {
InheritedData.of(context)?.data = value.toString();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('appMenu02 option: $value')),
);
},
onCanceled: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('appMenu02: Nothing selected.')),
);
},
tooltip: "Here's a tip for you.",
elevation: 12,
icon: const Icon(Icons.tablet),
offset: const Offset(0, 65),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
color: Colors.deepOrangeAccent,
);
appMenu03 = AppPopupMenu<String>(
items: ['One', 'Two', 'Three'],
initialValue: 'Three',
onSelected: (String value) {
InheritedData.of(context)?.data = value;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('appMenu03 option: $value')),
);
},
onCanceled: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('appMenu03: Nothing selected.')),
);
},
tooltip: "Here's a tip for you.",
elevation: 8,
icon: const Icon(Icons.settings),
offset: const Offset(0, 45),
padding: const EdgeInsets.all(16),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Popup Menu Examples'),
actions: [
appMenu01,
appMenu02,
appMenu03.set(
initialValue: 'Three',
onCanceled: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('appMenu03: Nothing selected.')),
);
},
tooltip: "Here's a tip for you.",
elevation: 8,
icon: const Icon(Icons.settings),
offset: const Offset(0, 45),
padding: const EdgeInsets.all(16),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
),
],
),
body: const MenuOption(),
);
}
}
class MenuOption extends StatelessWidget {
const MenuOption({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final data = InheritedData.of(context)?.data ?? '';
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$data',
style: Theme.of(context).textTheme.headline4,
),
],
),
);
}
}
解释
- InheritedWidget: 使用
InheritedData
组件来传递数据给子组件。 - AppPopupMenu: 创建多个
AppPopupMenu
实例,分别设置不同的参数。 - onSelected 和 onCanceled: 当用户选择或取消选择菜单项时,显示相应的
SnackBar
提示信息。 - AppBar Actions: 在
AppBar
的actions
中添加AppPopupMenu
实例。
通过上述步骤,你可以轻松地在Flutter应用中集成并使用 app_popup_menu
插件,创建更美观和动态的弹出菜单。希望这个示例对你有所帮助!
更多关于Flutter弹出菜单插件app_popup_menu的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter弹出菜单插件app_popup_menu的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用app_popup_menu
插件来实现弹出菜单的示例代码。app_popup_menu
是一个用于在Flutter应用中创建弹出菜单的插件。
首先,确保你已经在pubspec.yaml
文件中添加了app_popup_menu
依赖:
dependencies:
flutter:
sdk: flutter
app_popup_menu: ^latest_version # 替换为最新的版本号
然后,运行flutter pub get
来安装依赖。
接下来是一个完整的示例,展示如何使用app_popup_menu
:
import 'package:flutter/material.dart';
import 'package:app_popup_menu/app_popup_menu.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(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Popup Menu Example'),
),
body: Center(
child: GestureDetector(
onLongPress: () {
showPopupMenu(
context: context,
builder: (BuildContext context) {
return PopupMenu(
menuItems: [
PopupMenuItem(
value: 'Item 1',
child: Text('Item 1'),
),
PopupMenuItem(
value: 'Item 2',
child: Text('Item 2'),
),
PopupMenuItem(
value: 'Item 3',
child: Text('Item 3'),
),
],
onSelected: (String value) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Selected: $value'),
),
);
},
);
},
);
},
child: Container(
width: 200,
height: 100,
color: Colors.grey.withOpacity(0.5),
child: Center(
child: Text(
'Long Press to Show Menu',
style: TextStyle(fontSize: 24),
),
),
),
),
),
);
}
}
// 这是一个自定义的 showPopupMenu 函数,因为 app_popup_menu 插件没有直接提供该函数。
// 你可以根据插件的 API 自行封装一个类似的函数,这里是一个简单的示例。
Future<void> showPopupMenu({
required BuildContext context,
required PopupMenuBuilder builder,
}) async {
final overlay = Overlay.of(context)!;
final relativeRect = RelativeRect.fromRect(
Rect.fromPoints(
context.findRenderObject()!.localToGlobal(Offset.zero),
context.findRenderObject()!.localToGlobal(context.size!.bottomRight(Offset.zero)),
),
Offset.zero & overlay!.size,
);
final _menu = builder(context);
final _controller = OverlayEntry(
builder: (context) => Positioned(
width: _menu.preferredSize.width,
height: _menu.preferredSize.height,
left: relativeRect.left,
top: relativeRect.top + context.findRenderObject()!.size.height,
child: Material(
elevation: 8.0,
child: _menu,
),
),
);
overlay.insert(_controller);
_controller.resultFuture.whenComplete(() => _controller.remove());
// 你可以在这里添加逻辑来处理点击外部区域时关闭菜单
// 例如使用 GestureDetector 监听点击事件,然后调用 _controller.remove()
}
// PopupMenu 和 PopupMenuItem 需要根据 app_popup_menu 插件的实际 API 来定义
// 以下是一个假设的 PopupMenu 和 PopupMenuItem 示例
class PopupMenu extends StatelessWidget {
final List<PopupMenuItem> menuItems;
final ValueChanged<dynamic> onSelected;
PopupMenu({required this.menuItems, required this.onSelected});
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: menuItems.map((item) {
return GestureDetector(
onTap: () => onSelected(item.value),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: item.child,
),
);
}).toList(),
);
}
Size get preferredSize => Size(double.infinity, menuItems.length * 56.0); // 假设每个菜单项的高度为 56
}
class PopupMenuItem {
final dynamic value;
final Widget child;
PopupMenuItem({required this.value, required this.child});
}
typedef PopupMenuBuilder = Widget Function(BuildContext context);
注意:
app_popup_menu
插件的实际API可能与上述示例中的PopupMenu
和PopupMenuItem
有所不同。你需要查阅插件的官方文档或源代码以获取准确的用法。- 上述代码中的
showPopupMenu
函数是一个自定义的示例,用于展示如何在Flutter中实现弹出菜单的功能。实际使用时,你可能需要根据app_popup_menu
插件提供的API进行调整。 - 由于
app_popup_menu
插件的API可能会更新,建议查阅最新的插件文档或源代码以获取最新的用法。