我的网站是用 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),
),*/
),
],
),
),
)),
));
}
}
PopupMenuButton
使用
child
参数指定要显示为按钮的内容,使用 onSelected
指定如何处理 PopupMenuItem
处提供的值,并使用 itemBuilder
来构建项目。
enum Options { changePassword, logout }
NavbarItem
包裹的 AbsorbPointer
以覆盖其 onPressed
功能。final navbarItem = AbsorbPointer(
child: NavbarItem(
text: 'Salir',
icon: Icons.exit_to_app_outlined,
onPressed: () {},
),
);
void onSelected(item) {
switch (item) {
case Options.changePassword:
debugPrint('Change Password pressed');
break;
case Options.logout:
debugPrint('Change Password pressed');
break;
}
}
List<PopupMenuEntry<Options>> itemBuilder(context) => [
const PopupMenuItem(
value: Options.changePassword,
child: Text('Change Password'),
),
const PopupMenuItem(
value: Options.logout,
child: Text('Logout'),
),
];
PopupMenuButton(
onSelected: onSelected,
itemBuilder: itemBuilder,
child: navbarItem,
),