nav_bar_config.dart 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_riverpod/flutter_riverpod.dart';
  4. /// NavBar 配置,由各页面在 build 中设置,AppShell 统一渲染
  5. class NavBarConfig {
  6. final String title;
  7. final bool showBack;
  8. final bool showRight;
  9. final Widget? rightWidget;
  10. final VoidCallback? onBack;
  11. final IconData? leadingIcon;
  12. final bool hasFilter;
  13. final int filterVersion;
  14. const NavBarConfig({
  15. required this.title,
  16. this.showBack = false,
  17. this.showRight = false,
  18. this.rightWidget,
  19. this.onBack,
  20. this.leadingIcon,
  21. this.hasFilter = false,
  22. this.filterVersion = 0,
  23. });
  24. /// 根页面默认配置(无返回按钮)
  25. static const home = NavBarConfig(title: 'TBOSS 工作台', showBack: false);
  26. static const messages = NavBarConfig(title: '消息', showBack: false);
  27. static const profile = NavBarConfig(title: '我的', showBack: false);
  28. /// 带返回按钮的页面快捷构造
  29. factory NavBarConfig.withBack(String title, {VoidCallback? onBack}) {
  30. return NavBarConfig(title: title, showBack: true, onBack: onBack);
  31. }
  32. /// 带返回按钮 + 右侧按钮的页面快捷构造
  33. factory NavBarConfig.withRight(
  34. String title, {
  35. required Widget rightWidget,
  36. VoidCallback? onBack,
  37. }) {
  38. return NavBarConfig(
  39. title: title,
  40. showBack: true,
  41. showRight: true,
  42. rightWidget: rightWidget,
  43. onBack: onBack,
  44. );
  45. }
  46. @override
  47. bool operator ==(Object other) =>
  48. other is NavBarConfig &&
  49. other.title == title &&
  50. other.showBack == showBack &&
  51. other.showRight == showRight &&
  52. other.hasFilter == hasFilter &&
  53. other.filterVersion == filterVersion;
  54. // 故意不比较 onBack / rightWidget / leadingIcon,避免每次 build 新闭包触发无限重建
  55. @override
  56. int get hashCode =>
  57. Object.hash(title, showBack, showRight, hasFilter, filterVersion);
  58. }
  59. /// NavBar 配置变更器,内部做相等判断避免无限重建
  60. ///
  61. /// 通过 [Timer.run] 将状态更新推迟到事件循环下一个 tick,
  62. /// 避免子页面在 build 中更新 provider 时与 AppShell watch 冲突。
  63. class NavBarConfigNotifier extends StateNotifier<NavBarConfig> {
  64. NavBarConfigNotifier() : super(NavBarConfig.home);
  65. void update(NavBarConfig config) {
  66. if (state != config) {
  67. Future.microtask(() {
  68. if (mounted) state = config;
  69. });
  70. }
  71. }
  72. }
  73. /// NavBar 配置的 Provider —— 各页面在 build 中更新,AppShell 统一消费
  74. final navBarConfigProvider =
  75. StateNotifierProvider<NavBarConfigNotifier, NavBarConfig>(
  76. (ref) => NavBarConfigNotifier(),
  77. );