Flutter侧边栏菜单无法匹配参考设计,求修改方案
Flutter侧边栏菜单复刻问题
问题描述
我正在Flutter中开发侧边栏菜单,尝试复刻参考设计的外观与交互效果,但当前实现无法达到预期效果。
参考设计
当前实现效果
当前代码
bool _isHovered = false; int _selectedActivityLogIndex = 0; int _selectedSidebarIndex = 0; void _setHovered(bool isHovered) { setState(() { _isHovered = isHovered; }); } @override Widget build(BuildContext context) { return Scaffold( body: Row( children: [ MouseRegion( onEnter: (_) => _setHovered(true), onExit: (_) => _setHovered(false), child: AnimatedContainer( duration: const Duration(milliseconds: 300), width: _isHovered ? 200.0 : 60.0, color: AppColors.sideBarMenuColor, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSidebarItem(SideBarMenuIcons.applicantSideMenuIcon1, 'Overview', 0), _buildSidebarItem(SideBarMenuIcons.applicantSideMenuIcon7, 'DBS', 1), _buildSidebarItem(SideBarMenuIcons.applicantSideMenuIcon6, 'Basic Disclosure', 2), _buildSidebarItem(SideBarMenuIcons.applicantSideMenuIcon5, 'Reference Check', 3), _buildSidebarItem(SideBarMenuIcons.applicantSideMenuIcon4, 'Right to Work', 4), _buildSidebarItem(SideBarMenuIcons.applicantSideMenuIcon3, 'Qualification', 5), _buildSidebarItem(SideBarMenuIcons.applicantSideMenuIcon2, 'ID', 6), ], ), ), ), Expanded( flex: 6, child: SingleChildScrollView( padding: const EdgeInsets.all(20.0), child: _buildContent(_selectedSidebarIndex), ), ), ], ), ); } Widget _buildSidebarItem(String assetPath, String title, int index) { final isSelected = index == _selectedSidebarIndex; return GestureDetector( onTap: () { setState(() { _selectedSidebarIndex = index; }); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.only( bottomRight: Radius.circular(isSelected ? 20.0 : 0.0), topRight: Radius.circular(isSelected ? 20.0 : 0.0), ), color: isSelected ? AppColors.kWhite : AppColors.sideBarMenuColor, ), padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(width: 20.0), SvgPicture.asset( assetPath, width: 20.0, height: 20.0, color: AppColors.kSideMenuIconColor, ), if (_isHovered) ...[ const SizedBox(width: 16.0), Expanded( child: Text( title, overflow: TextOverflow.ellipsis, style: TextStyle( color: isSelected ? AppColors.kBlueColor : Colors.white, ), textAlign: TextAlign.left, ), ), ], ], ), ), ); }
问题
我已实现侧边栏菜单,但设计效果与参考示例不符。请问如何修改代码或调整实现思路,以达成示例中的设计效果?
解决方案
对比参考设计和你的实现,主要需要调整以下几点:
选中项视觉优化
参考设计中选中项左侧有蓝色竖线,且白色背景从左侧边缘延伸到右侧圆角。修改_buildSidebarItem的BoxDecoration:decoration: BoxDecoration( borderRadius: BorderRadius.only( bottomRight: Radius.circular(20.0), topRight: Radius.circular(20.0), ), color: isSelected ? AppColors.kWhite : AppColors.sideBarMenuColor, border: isSelected ? Border(left: BorderSide(color: AppColors.kBlueColor, width: 4)) : null, ),同时把选中项的图标颜色改为蓝色:
color: isSelected ? AppColors.kBlueColor : AppColors.kSideMenuIconColor,菜单项布局调整
参考设计的菜单项高度更高,调整容器padding增大垂直间距:padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 20.0),移除
Row内的SizedBox(width:20.0),避免和容器水平padding重复。文字过渡动画
给文字添加淡入淡出效果,替换原文字部分代码:if (_isHovered) ...[ const SizedBox(width: 16.0), Expanded( child: AnimatedOpacity( opacity: _isHovered ? 1.0 : 0.0, duration: const Duration(milliseconds: 200), child: Text( title, overflow: TextOverflow.ellipsis, style: TextStyle( color: isSelected ? AppColors.kBlueColor : Colors.white, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), textAlign: TextAlign.left, ), ), ), ],单菜单项hover响应
把MouseRegion移到每个菜单项内部,实现单独hover效果:
先新增变量int _hoveredIndex = -1;,然后修改_buildSidebarItem:return MouseRegion( onEnter: (_) => setState(() => _hoveredIndex = index), onExit: (_) => setState(() => _hoveredIndex = -1), child: GestureDetector( onTap: () { setState(() { _selectedSidebarIndex = index; }); }, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.only( bottomRight: Radius.circular(20.0), topRight: Radius.circular(20.0), ), color: isSelected ? AppColors.kWhite : (_hoveredIndex == index ? AppColors.sideBarMenuHoverColor : AppColors.sideBarMenuColor), border: isSelected ? Border(left: BorderSide(color: AppColors.kBlueColor, width: 4)) : null, ), padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 20.0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ SvgPicture.asset( assetPath, width: 20.0, height: 20.0, color: isSelected ? AppColors.kBlueColor : AppColors.kSideMenuIconColor, ), if (_isHovered || _hoveredIndex == index) ...[ const SizedBox(width: 16.0), Expanded( child: AnimatedOpacity( opacity: (_isHovered || _hoveredIndex == index) ? 1.0 : 0.0, duration: const Duration(milliseconds: 200), child: Text( title, overflow: TextOverflow.ellipsis, style: TextStyle( color: isSelected ? AppColors.kBlueColor : Colors.white, fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal, ), textAlign: TextAlign.left, ), ), ), ], ], ), ), ), );注意新增
AppColors.sideBarMenuHoverColor作为hover时的背景色。
按上述调整后,即可贴近参考设计的外观与交互效果。
内容的提问来源于stack exchange,提问作者Muhammad Ali
相关产品推荐
相关产品推荐




