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

发布于 1周前 作者 songsunli 来自 Flutter

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. 自定义了 FocusedMenuCustomitemBuilder 以自定义菜单项的样式,并处理菜单项的点击事件。

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

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

回到顶部