flutter 中导航栏的子菜单

问题描述 投票:0回答:1

我的网站是用 flutter 制作的,当您单击用户名 (users.firstName) 的 NavbarItem 时,我需要为我的导航栏创建一个子菜单。 下面我给大家分享一下代码。

class NavBar extends StatelessWidget {
  const NavBar({Key? key});

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final user = Provider.of<AuthProvider>(context).user!;
    final token = LocalStorage.prefs.getString('token');
    return Container(
      width: double.infinity,
      height: 75,
      decoration: buildBoxDecoration(),
      child: Row(
        children: [
          if (size.width <= 779) ...[
            IconButton(
              onPressed: () {
                SideMenuProvider.openMenu();
              },
              icon: const Icon(Icons.menu_outlined),
            ),
            const Spacer(),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 2),
              child: Container(
                width: 250,
                child: const AutoSizeText(
                  'SISTEMA WEB DE COSTOS Y RENTABILIDAD DEL PROCESO DEL CULTIVO DEL BANANO',
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                  ),
                  maxLines: 5, // Número máximo de líneas permitidas
                  minFontSize: 10, // Tamaño de fuente mínimo
                  maxFontSize: 30, // Tamaño de fuente máximo
                  overflow: TextOverflow.ellipsis, // Opción de desbordamiento
                ),
              ),
            ),
          ],
          if (size.width >= 779) ...[
            const SizedBox(
              width: 5,
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 2),
              child: Container(
                width: 250,
                child: const AutoSizeText(
                  'SISTEMA WEB DE COSTOS Y RENTABILIDAD DEL PROCESO DEL CULTIVO DEL BANANO',
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                  ),
                  maxLines: 5, // Número máximo de líneas permitidas
                  minFontSize: 10, // Tamaño de fuente mínimo
                  maxFontSize: 30, // Tamaño de fuente máximo
                  overflow: TextOverflow.ellipsis, // Opción de desbordamiento
                ),
              ),
            ),
            const Spacer(),
            NavbarItem(
                text: 'Inicio',
                icon: Icons.home_sharp,
                onPressed: () {
                  NavigationService.replaceTo(Flurorouter.dashboardRoute);
                }),
            /*NavbarItem(
                text: 'Opciones de perfil',
                icon: Icons.settings,
                onPressed: () {}),*/
            NavbarItem(
                text: 'Datos',
                icon: Icons.people,
                onPressed: () {
                  NavigationService.replaceTo('/dashboard/info/$token');
                },
                isActive: false),
            NavbarItem(
                text: 'Password',
                icon: Icons.people,
                onPressed: () {
                  NavigationService.replaceTo(Flurorouter.changePassRoute);
                },
                isActive: false),
            NavbarItem(
                text: user.firstName,
                icon: Icons.people,
                onPressed: () {
                  //crearMenu(context);
                },
                isActive: false),
            NavbarItem(
              text: 'Salir',
              icon: Icons.exit_to_app_outlined,
              onPressed: () {
                Provider.of<AuthProvider>(context, listen: false).logout();
              },
            ),
          ],
        ],
      ),
    );
  }

  BoxDecoration buildBoxDecoration() => const BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.centerLeft, // Comienza desde la izquierda
            end: Alignment.centerRight, // Termina en la derecha
            colors: [
              Color(0xFF679C64), // Color de inicio
              Color(0xFFADCFAB), // Color de finalización
            ],
          ),
          boxShadow: [
            BoxShadow(
              blurRadius: 5,
              color: Colors.black12,
            )
          ]);

NavbarItem 包含:

class NavbarItem extends StatefulWidget {
  final String text;
  final IconData icon;
  final bool isActive;
  final Function onPressed;

  const NavbarItem({
    required this.text,
    required this.icon,
    this.isActive = false,
    required this.onPressed,
  });

  @override
  State<NavbarItem> createState() => _NavbarItemState();
}

class _NavbarItemState extends State<NavbarItem> {
  bool isHover = false;

  @override
  Widget build(BuildContext context) {
    return Container(
      child: InkWell(
        onTap: widget.isActive ? null : () => widget.onPressed(),
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 15),
          child: MouseRegion(
            onEnter: (_) => setState(() {
              isHover = true;
            }),
            onExit: (_) => setState(() {
              isHover = false;
            }),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                Icon(widget.icon),
                Text(
                  widget.text,
                  style: TextStyle(
                    decoration: isHover
                        ? TextDecoration.underline
                        : TextDecoration.none,
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

我该怎么做?

我需要更改某些小部件的 NavbarItem,以便我能够显示更多选项来获取子菜单的行为。 我还想知道这些子菜单选项是否可以自定义,就像下面的小部件一样,它是我用于侧面菜单的 AnimatedContainer,我喜欢它的工作方式,并且我想将该小部件集成为自定义选项:

class SidebarItem extends StatefulWidget {
  final String text;
  final Function onPressed;
  final bool isActive;
  final IconData icon;

  const SidebarItem({
    Key? key,
    required this.text,
    required this.onPressed,
    this.isActive = false,
    required this.icon,
  }) : super(key: key);

  @override
  State<SidebarItem> createState() => _SidebarItemState();
}

class _SidebarItemState extends State<SidebarItem> {
  bool isHover = false;

  @override
  Widget build(BuildContext context) {
    Color backgroundColor = isHover
        ? const Color(0xFF184D26)
        : widget.isActive
            ? const Color(0xFF184D26)
            : Colors.transparent;
    return AnimatedContainer(
        duration: const Duration(milliseconds: 250),
        color: backgroundColor,
        child: Material(
          color: Colors.transparent,
          child: InkWell(
              onTap: widget.isActive ? null : () => widget.onPressed(),
              child: Padding(
                padding:
                    const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
                child: MouseRegion(
                  onEnter: (_) => setState(() {
                    isHover = true;
                  }),
                  onExit: (_) => setState(() {
                    isHover = false;
                  }),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Icon(widget.icon),
                      const SizedBox(
                        width: 5,
                      ),
                      Text(
                        widget.text,
                        /*style: GoogleFonts.roboto(
                          fontSize: 14,
                          color: Colors.black.withOpacity(0.8),
                        ),*/
                      ),
                    ],
                  ),
                ),
              )),
        ));
  }
}

我想实现这样的目标:我需要显示两个选项“更改密码”和“更新信息”。 enter image description here

flutter dart web navbar
1个回答
0
投票

尝试
PopupMenuButton

使用

child
参数指定要显示为按钮的内容,使用
onSelected
指定如何处理
PopupMenuItem
处提供的值,并使用
itemBuilder
来构建项目。

  1. 在本例中声明选项列表或枚举以更具描述性`
enum Options { changePassword, logout }
  1. 子项用作按钮,否则可能会显示默认的 3 点图标。这是用
    NavbarItem
    包裹的
    AbsorbPointer
    以覆盖其
    onPressed
    功能。
final navbarItem = AbsorbPointer(
  child: NavbarItem(
    text: 'Salir',
    icon: Icons.exit_to_app_outlined,
    onPressed: () {},
  ),
);
  1. 已选择
void onSelected(item) {
  switch (item) {
    case Options.changePassword:
      debugPrint('Change Password pressed');
      break;
    case Options.logout:
      debugPrint('Change Password pressed');
      break;
  }
}
  1. 项目生成器
List<PopupMenuEntry<Options>> itemBuilder(context) => [
      const PopupMenuItem(
        value: Options.changePassword,
        child: Text('Change Password'),
      ),
      const PopupMenuItem(
        value: Options.logout,
        child: Text('Logout'),
      ),
    ];
  1. 将其调整到您想要使用的位置
PopupMenuButton(
  onSelected: onSelected,
  itemBuilder: itemBuilder,
  child: navbarItem,
),
© www.soinside.com 2019 - 2024. All rights reserved.