Flutter自定义聚焦菜单插件focused_menu_custom的使用

Flutter自定义聚焦菜单插件focused_menu_custom的使用

focused_menu_custom 是一个易于实现的包,用于在Flutter应用程序中添加长按聚焦菜单。该插件允许您将聚焦菜单添加到任何小部件,并根据您的应用需求自定义菜单和动画。

当前功能

  • 将聚焦菜单添加到任何小部件。
  • 根据应用程序需求自定义聚焦菜单和动画。

演示

Focused Menu Demo

使用方法

要使用此插件,只需将想要添加聚焦菜单的小部件用 FocusedMenuHolder 包裹起来即可:

Expanded(
  child: GridView(
    physics: BouncingScrollPhysics(),
    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
    children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        .map((e) => FocusedMenuHolder(
              menuWidth: MediaQuery.of(context).size.width * 0.50,
              blurSize: 5.0,
              menuItemExtent: 45,
              menuBoxDecoration: BoxDecoration(
                  color: Colors.grey,
                  borderRadius: BorderRadius.all(Radius.circular(15.0))),
              duration: Duration(milliseconds: 100),
              animateMenuItems: true,
              blurBackgroundColor: Colors.black54,
              openWithTap: true, // 点击打开而不是长按
              menuOffset: 10.0, // 菜单项显示的偏移值
              bottomOffsetHeight: 80.0, // 底部导航栏的偏移高度
              menuItems: <FocusedMenuItem>[
                FocusedMenuItem(
                    title: Text("Open"),
                    trailingIcon: Icon(Icons.open_in_new),
                    onPressed: () {
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => ScreenTwo()));
                    }),
                FocusedMenuItem(title: Text("Share"), trailingIcon: Icon(Icons.share), onPressed: () {}),
                FocusedMenuItem(title: Text("Favorite"), trailingIcon: Icon(Icons.favorite_border), onPressed: () {}),
                FocusedMenuItem(
                    title: Text("Delete", style: TextStyle(color: Colors.redAccent)),
                    trailingIcon: Icon(Icons.delete, color: Colors.redAccent),
                    onPressed: () {}),
              ],
              onPressed: () {},
              child: Card(
                child: Column(
                  children: <Widget>[
                    Image.asset("assets/images/image_$e.jpg"),
                  ],
                ),
              ),
            ))
        .toList(),
  ),
),

示例代码

以下是一个完整的示例代码,展示如何在Flutter应用中使用 focused_menu_custom 插件:

import 'package:flutter/material.dart';
import 'package:focused_menu_custom/focused_menu.dart';
import 'package:focused_menu_custom/modals.dart';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Focused Menu Custom',
      theme: ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.red,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      themeMode: ThemeMode.light,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Container(
          child: Padding(
            padding: const EdgeInsets.all(15.0),
            child: Column(
              children: <Widget>[
                Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Text(
                      "Music Albums",
                      style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
                    ),
                    Expanded(child: Center()),
                    IconButton(icon: Icon(Icons.shopping_cart), onPressed: () {}),
                    CircleAvatar(
                      child: Image.asset("assets/images/dp_default.png"),
                    )
                  ],
                ),
                SizedBox(height: 10),
                TextField(
                  decoration: InputDecoration(
                      border: InputBorder.none,
                      hintText: "Look for your Interest!",
                      fillColor: Colors.grey.shade200,
                      filled: true),
                ),
                SizedBox(height: 10),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    DropdownButton(
                        style: TextStyle(fontSize: 15, color: Colors.black),
                        icon: Icon(Icons.keyboard_arrow_down),
                        underline: Container(
                          color: Colors.white,
                        ),
                        items: ["Featured", "Most Rated", "Recent", "Popular"]
                            .map<DropdownMenuItem>(
                                (e) => DropdownMenuItem(child: Text(e)))
                            .toList(),
                        onChanged: (newItem) {}),
                    IconButton(icon: Icon(Icons.sort), onPressed: () {})
                  ],
                ),
                SizedBox(height: 10),
                Expanded(
                  child: GridView(
                    physics: BouncingScrollPhysics(),
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                        crossAxisCount: 2),
                    children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
                        .map((e) => FocusedMenuHolder(
                              menuWidth: MediaQuery.of(context).size.width * 0.50,
                              blurSize: 5.0,
                              menuItemExtent: 45,
                              menuBoxDecoration: BoxDecoration(
                                  color: Colors.grey,
                                  borderRadius:
                                      BorderRadius.all(Radius.circular(15.0))),
                              duration: Duration(milliseconds: 100),
                              animateMenuItems: true,
                              blurBackgroundColor: Colors.black54,
                              bottomOffsetHeight: 100,
                              openWithTap: true,
                              menuItems: <FocusedMenuItem>[
                                FocusedMenuItem(
                                    title: Text("Open"),
                                    trailingIcon: Icon(Icons.open_in_new),
                                    onPressed: () {
                                      // Navigate to another screen
                                    }),
                                FocusedMenuItem(
                                    title: Text("Share"),
                                    trailingIcon: Icon(Icons.share),
                                    onPressed: () {}),
                                FocusedMenuItem(
                                    title: Text("Favorite"),
                                    trailingIcon: Icon(Icons.favorite_border),
                                    onPressed: () {}),
                                FocusedMenuItem(
                                    title: Text(
                                      "Delete",
                                      style: TextStyle(color: Colors.redAccent),
                                    ),
                                    trailingIcon: Icon(
                                      Icons.delete,
                                      color: Colors.redAccent,
                                    ),
                                    onPressed: () {}),
                              ],
                              onPressed: () {},
                              child: Card(
                                child: Column(
                                  children: <Widget>[
                                    Image.asset("assets/images/image_$e.jpg"),
                                  ],
                                ),
                              ),
                            ))
                        .toList(),
                  ),
                ),
              ],
            ),
          ),
        ),
        bottomNavigationBar: BottomNavigationBar(items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(Icons.add), label: "Home"),
          BottomNavigationBarItem(icon: Icon(Icons.add), label: "Menu 2"),
          BottomNavigationBarItem(icon: Icon(Icons.add), label: "Menu 3"),
          BottomNavigationBarItem(icon: Icon(Icons.add), label: "Menu 4"),
          BottomNavigationBarItem(icon: Icon(Icons.add), label: "Menu 5"),
        ]),
      ),
    );
  }
}

更多关于Flutter自定义聚焦菜单插件focused_menu_custom的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义聚焦菜单插件focused_menu_custom的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter中使用自定义聚焦菜单插件 focused_menu_custom 的一个代码示例。这个示例展示了如何创建并显示一个自定义聚焦菜单。

首先,确保你已经在你的 pubspec.yaml 文件中添加了 focused_menu_custom 依赖项:

dependencies:
  flutter:
    sdk: flutter
  focused_menu_custom: ^最新版本号  # 替换为实际的最新版本号

然后运行 flutter pub get 来获取依赖项。

接下来,在你的 Dart 文件中使用 FocusedMenuCustom 组件。以下是一个完整的示例:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Focused Menu Custom Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Focused Menu Custom Demo'),
        ),
        body: Center(
          child: FocusedMenuCustomDemo(),
        ),
      ),
    );
  }
}

class FocusedMenuCustomDemo extends StatefulWidget {
  @override
  _FocusedMenuCustomDemoState createState() => _FocusedMenuCustomDemoState();
}

class _FocusedMenuCustomDemoState extends State<FocusedMenuCustomDemo> {
  final List<String> menuItems = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        showMenu(
          context: context,
          position: RelativeRect.fromLTRB(0, 0, 0, 0),
          items: menuItems.map<PopupMenuEntry<String>>((String item) {
            return PopupMenuItem<String>(
              value: item,
              child: Text(item),
            );
          }).toList(),
          elevation: 8.0,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          builder: (BuildContext context) {
            return Material(
              color: Colors.white,
              child: FocusedMenuCustom(
                menuItems: menuItems,
                onMenuItemSelected: (String selectedItem) {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('Selected: $selectedItem'),
                    ),
                  );
                },
                // 自定义菜单项样式
                itemBuilder: (context, index) {
                  return GestureDetector(
                    onTap: () {
                      Navigator.pop(context, menuItems[index]);
                    },
                    child: Container(
                      decoration: BoxDecoration(
                        border: Border(
                          bottom: BorderSide(
                            color: index == menuItems.indexOf(Navigator.popResult(context))
                                ? Colors.blue
                                : Colors.transparent,
                            width: 2.0,
                          ),
                        ),
                      ),
                      padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                      child: Text(
                        menuItems[index],
                        style: TextStyle(
                          color: index == menuItems.indexOf(Navigator.popResult(context))
                              ? Colors.blue
                              : Colors.black,
                        ),
                      ),
                    ),
                  );
                },
              ),
            );
          },
        );
      },
      child: Container(
        width: 100,
        height: 100,
        color: Colors.blue.withOpacity(0.5),
        child: Center(
          child: Text(
            'Tap me',
            style: TextStyle(color: Colors.white),
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 添加了 focused_menu_custom 依赖项。
  2. 创建了一个包含菜单项的列表。
  3. 使用 GestureDetector 监听点击事件。
  4. 使用 showMenu 显示菜单。
  5. 自定义了 FocusedMenuCustom 的 itemBuilder 以自定义菜单项的样式,并处理菜单项的点击事件。

请注意,Navigator.popResult(context) 并不存在于 Flutter 的标准库中,这里只是为了演示如何获取用户选择的菜单项。在实际应用中,你应该使用 Navigator.pop(context, result) 返回结果,并在调用 showMenu 的地方使用 await 关键字获取结果。由于 FocusedMenuCustom 插件可能不支持这种直接的结果返回方式,你可能需要调整逻辑以适应插件的实际行为。

希望这个示例对你有帮助!

回到顶部