Flutter深度菜单插件deep_menu的使用

Flutter深度菜单插件deep_menu的使用

特性

DeepMenu 插件在长按后打开菜单。支持顶部和底部菜单。

演示

使用方法

示例代码

DeepMenu(
    child: Card(
        child: Padding(
        padding: EdgeInsets.all(10),
        child: Text("Message!"),
        )),
    ),
    bodyMenu: Column(
        children: [
            ElevatedButton(onPressed: () {
                Navigator.of(context).pop();
            }, child: Text("保存"))
        ],
    ),
    headMenu: Column(
        children: [
            ElevatedButton(onPressed: () {
                Navigator.of(context).pop();
            }, child: Text("移除"))
        ],
    ),
)

完整示例代码

import 'package:flutter/material.dart';
import 'package:deep_menu/deep_menu.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: CustomScrollView(
          slivers: [
            SliverGrid(
              gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200.0
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Padding(
                    padding: const EdgeInsets.all(4.0),
                    child: DeepMenu(
                      child: MessageCard(title: "Deep menu $index"),
                      bodyMenu: _buildMenu(context)
                    ),
                  );
                },
                childCount: 2,
              ),
            ),
            const SliverToBoxAdapter(
              child: Divider(),
            ),
            SliverList(
                delegate: SliverChildListDelegate(List.generate(
              2,
              (index) => Padding(
                padding: const EdgeInsets.all(4.0),
                child: DeepMenu(
                  child: MessageCard(title: "Body menu $index"),
                  bodyMenu: _buildMenu(context),
                ),
              ),
            ).toList())),
            const SliverToBoxAdapter(
              child: Divider(),
            ),
            SliverGrid(
              gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200.0
              ),
              delegate: SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                  return Padding(
                    padding: const EdgeInsets.all(4.0),
                    child: DeepMenu(
                      child: MessageCard(title: "Body and Head $index"),
                      bodyMenu: _buildMenu(context),
                      headMenu: _buildHeadMenu(context),
                    ),
                  );
                },
                childCount: 2,
              ),
            ),
            const SliverToBoxAdapter(
              child: Divider(),
            ),
            SliverList(
                delegate: SliverChildListDelegate(List.generate(
              2,
              (index) => Padding(
                padding: const EdgeInsets.all(4.0),
                child: DeepMenu(
                  child: MessageCard(title: "Head menu $index"),
                  headMenu: _buildHeadMenu(context),
                ),
              ),
            ).toList())),
            const SliverToBoxAdapter(
              child: Divider(),
            ),
            SliverList(
                delegate: SliverChildListDelegate(List.generate(
              2,
              (index) => Padding(
                padding: const EdgeInsets.all(4.0),
                child: DeepMenu(
                  child: const MessageCard(title: "Body and Head menues"),
                  bodyMenu: _buildMenu(context),
                  headMenu: _buildHeadMenu(context),
                ),
              ),
            ).toList())),
            SliverToBoxAdapter(
              child: Padding(
                padding: const EdgeInsets.all(4.0),
                child: SizedBox(
                  height: MediaQuery.of(context).size.height * 0.8,
                  child: DeepMenu(
                    child: const MessageCard(title: "Big element with scroll"),
                    bodyMenu: _buildMenu(context),
                    headMenu: _buildHeadMenu(context),
                  ),
                ),
              ),
            )
          ],
        ));
  }

  Widget _buildMenu(BuildContext context) {
    return DeepMenuList(items: [
      DeepMenuItem(
          label: const Text("喜欢"),
          icon: const Icon(Icons.favorite_border),
          onTap: () {
            Navigator.pop(context);
            // 忽略:避免打印
            print('LIKE');
          }),
      DeepMenuItem(
          label: const Text("保存"),
          icon: const Icon(Icons.save),
          onTap: () {
            Navigator.pop(context);
            // 忽略:避免打印
            print('SAVE');
          }),
      DeepMenuItem(
          label: const Text(
            "删除",
            style: TextStyle(color: Colors.red),
          ),
          icon: const Icon(
            Icons.delete,
            color: Colors.red,
          ),
          onTap: () {
            Navigator.pop(context);
            // 忽略:避免打印
            print('DELETE');
          })
    ]);
  }

  Widget _buildHeadMenu(BuildContext context) {
    // 忽略:更推荐函数声明
    void Function() goBack = () {
      Navigator.pop(context);
    };

    return Container(
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(30), color: Colors.white),
      height: 50,
      child: Material(
        color: Colors.transparent,
        child: ListView(
          padding: const EdgeInsets.symmetric(horizontal: 10),
          scrollDirection: Axis.horizontal,
          children: [
            IconButton(onPressed: goBack, icon: const Icon(Icons.save)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.edit)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.refresh)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.share)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.person)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.delete)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.zoom_in)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.zoom_out)),
            IconButton(onPressed: goBack, icon: const Icon(Icons.flight))
          ],
        ),
      ),
    );
  }
}

class MessageCard extends StatelessWidget {
  final String title;
  const MessageCard({
    required this.title,
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Card(
      margin: const EdgeInsets.all(0),
      child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10),
          child: Center(child: Text(title))),
    );
  }
}

更多关于Flutter深度菜单插件deep_menu的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter深度菜单插件deep_menu的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用deep_menu插件的详细代码案例。deep_menu插件通常用于实现类似于iOS的3D Touch或Android的长按菜单效果。需要注意的是,这个插件可能不是官方维护的,因此在实际项目中使用时,请确保查看其最新的文档和兼容性。

首先,你需要在你的pubspec.yaml文件中添加deep_menu依赖:

dependencies:
  flutter:
    sdk: flutter
  deep_menu: ^最新版本号  # 请替换为实际可用的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们将展示如何在一个简单的Flutter应用中实现深度菜单效果。

主文件:main.dart

import 'package:flutter/material.dart';
import 'package:deep_menu/deep_menu.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Deep Menu Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<MenuItem> menuItems = [
    MenuItem(title: 'Action 1', icon: Icons.star),
    MenuItem(title: 'Action 2', icon: Icons.favorite),
    MenuItem(title: 'Action 3', icon: Icons.settings),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Deep Menu Example'),
      ),
      body: Center(
        child: DeepMenu(
          child: GestureDetector(
            onLongPress: () {
              showDeepMenu(
                context: context,
                items: menuItems,
                onMenuItemClicked: (index) {
                  // Handle menu item click
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('You clicked: ${menuItems[index].title}'),
                    ),
                  );
                },
              );
            },
            child: Container(
              width: 200,
              height: 200,
              color: Colors.grey.withOpacity(0.5),
              alignment: Alignment.center,
              child: Text(
                'Long Press Me',
                style: TextStyle(fontSize: 24, color: Colors.black),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class MenuItem {
  final String title;
  final IconData icon;

  MenuItem({required this.title, required this.icon});
}

辅助文件:deep_menu.dart(假设这是插件提供的功能,实际使用时请根据插件文档调整)

由于deep_menu插件的具体实现可能不在你的控制范围内,以下是一个假设的实现,用于展示如何模拟一个深度菜单。在实际项目中,你需要根据插件的实际API来调整这部分代码。

import 'package:flutter/material.dart';
import 'dart:ui' show window;

void showDeepMenu({
  required BuildContext context,
  required List<MenuItem> items,
  required ValueChanged<int> onMenuItemClicked,
}) {
  final RenderBox box = context.findRenderObject() as RenderBox;
  final Offset position = box.localToGlobal(Offset.zero);
  final double screenHeight = window.physicalSize.height;
  final double screenWidth = window.physicalSize.width;

  showMenu<int>(
    context: context,
    position: RelativeRect.fromLTRB(
      position.dx,
      position.dy + box.size.height,
      position.dx + box.size.width,
      position.dy + box.size.height,
    ),
    items: items.asMap().entries.map((entry) {
      final int index = entry.key;
      final MenuItem menuItem = entry.value;
      return PopupMenuItem<int>(
        value: index,
        child: Row(
          children: <Widget>[
            Icon(menuItem.icon),
            SizedBox(width: 16),
            Text(menuItem.title),
          ],
        ),
      );
    }).toList(),
    onSelected: onMenuItemClicked,
  );
}

注意

  1. 上面的deep_menu.dart文件是一个假设的实现,用于展示如何模拟一个深度菜单。在实际项目中,你需要根据deep_menu插件的实际API来实现。
  2. MenuItem类是一个简单的数据类,用于存储菜单项的标题和图标。
  3. showDeepMenu函数中,我们使用showMenu函数来显示一个弹出菜单,该菜单项基于提供的MenuItem列表生成。

在实际项目中,请确保阅读并遵循deep_menu插件的官方文档,因为插件的API可能会发生变化。

回到顶部