side_bar.dart 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. part of "./side_nav.dart";
  2. class _SideBar extends StatefulWidget {
  3. /// 导航Id
  4. final int? navId;
  5. /// 菜单项集合
  6. final List<VSideNavMenuItem> items;
  7. final VSideNavViewController controller;
  8. const _SideBar({
  9. required this.controller,
  10. this.navId,
  11. required this.items,
  12. });
  13. @override
  14. State<StatefulWidget> createState() => _SideBarState();
  15. }
  16. class _SideBarState extends State<_SideBar> {
  17. static const double _cellHegiht = 68.0;
  18. @override
  19. void initState() {
  20. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  21. if (mounted) {
  22. widget.controller.routeChangedEvent.addListener(_onRouteChanged);
  23. }
  24. });
  25. super.initState();
  26. }
  27. @override
  28. void dispose() {
  29. widget.controller.routeChangedEvent.removeListener(_onRouteChanged);
  30. super.dispose();
  31. }
  32. @override
  33. Widget build(BuildContext context) {
  34. return Scrollbar(
  35. thumbVisibility: true,
  36. child: ListView(
  37. padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 12),
  38. children: _buildChildren(context),
  39. ),
  40. );
  41. }
  42. List<Widget> _buildChildren(BuildContext context) {
  43. final children = <Widget>[];
  44. final hasAnyIcon = widget.items.any((e) => e.icon != null);
  45. final divider = Divider(
  46. height: 1,
  47. color: Colors.grey.shade400,
  48. indent: hasAnyIcon ? 36 : 0,
  49. endIndent: 12,
  50. );
  51. final count = widget.items.length;
  52. for (var i = 0; i < count; i++) {
  53. final item = widget.items[i];
  54. if (item.shouldRearrage) {
  55. children.add(const SizedBox(height: 32));
  56. } else if (i > 0) {
  57. children.add(divider);
  58. }
  59. final cell = _buildMenuCell(item);
  60. children.add(cell);
  61. }
  62. return children;
  63. }
  64. Widget _buildMenuCell(VSideNavMenuItem item) {
  65. final hasSection = item.route != null &&
  66. item.route!.name == widget.controller.currentRoute;
  67. final cell = Padding(
  68. padding: const EdgeInsets.symmetric(horizontal: 12),
  69. child: VListFormCell(
  70. height: _cellHegiht,
  71. leadingIcon: Container(
  72. alignment: Alignment.center,
  73. child: item.icon,
  74. ),
  75. leadingIconWidth: 36,
  76. label: item.title,
  77. onTap: () {
  78. _onItemTap(item, hasSection);
  79. },
  80. ),
  81. );
  82. if (hasSection) {
  83. return _buildSectionItem(cell);
  84. } else {
  85. return cell;
  86. }
  87. }
  88. Widget _buildSectionItem(Widget itemWidget) {
  89. return SizedBox(
  90. height: _cellHegiht,
  91. child: Stack(
  92. children: [
  93. itemWidget,
  94. Positioned.fill(
  95. child: Container(
  96. decoration: BoxDecoration(
  97. borderRadius: GlobalStyles.borderRadius,
  98. color: Theme.of(context).primaryColor.withOpacity(.2),
  99. ),
  100. ),
  101. ),
  102. ],
  103. ),
  104. );
  105. }
  106. void _onRouteChanged(_, String? e) {
  107. setState(() {});
  108. }
  109. void _onItemTap(VSideNavMenuItem item, bool hasSection) {
  110. if (item.onTap != null) {
  111. item.onTap!.call();
  112. return;
  113. }
  114. if (hasSection) {
  115. // 不可重复路由
  116. return;
  117. }
  118. if (item.pageBuilder != null) {
  119. widget.controller.pageChangedEvent.emit(this, item.pageBuilder!);
  120. }
  121. if (item.route != null) {
  122. Get.offAllNamed(item.route!.name, id: widget.navId);
  123. }
  124. }
  125. }