nav_bar_config.dart 2.5 KB

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