pencil_nav_bar.dart 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter/services.dart';
  3. import '../../core/theme/app_colors.dart';
  4. /// Pencil Component/NavBar — 对齐 Pencil 设计的导航栏
  5. ///
  6. /// 白色背景、居中深色标题、左侧返回按钮(绝对定位)、右侧可选操作按钮(绝对定位)
  7. /// 高度 56,padding [0, 16],自动设置白色状态栏
  8. class PencilNavBar extends StatelessWidget implements PreferredSizeWidget {
  9. final String title;
  10. final VoidCallback? onBack;
  11. final Widget? rightWidget;
  12. final bool showBack;
  13. final bool showRight;
  14. const PencilNavBar({
  15. super.key,
  16. required this.title,
  17. this.onBack,
  18. this.rightWidget,
  19. this.showBack = true,
  20. this.showRight = false,
  21. });
  22. @override
  23. Widget build(BuildContext context) {
  24. // 设置状态栏样式
  25. SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
  26. statusBarColor: AppColors.bgCard,
  27. statusBarIconBrightness: Brightness.dark,
  28. statusBarBrightness: Brightness.light,
  29. ));
  30. return Container(
  31. height: 56,
  32. padding: const EdgeInsets.symmetric(horizontal: 16),
  33. decoration: const BoxDecoration(
  34. color: AppColors.bgCard,
  35. ),
  36. child: Stack(
  37. alignment: Alignment.center,
  38. children: [
  39. // 标题 — 居中
  40. Text(
  41. title,
  42. style: const TextStyle(
  43. fontSize: AppFontSizes.title,
  44. fontWeight: FontWeight.w600,
  45. color: AppColors.textPrimary,
  46. ),
  47. textAlign: TextAlign.center,
  48. ),
  49. // 左侧返回按钮 — 绝对定位
  50. if (showBack)
  51. Positioned(
  52. left: 0,
  53. top: 0,
  54. bottom: 0,
  55. child: SizedBox(
  56. width: 56,
  57. height: 56,
  58. child: GestureDetector(
  59. onTap: onBack ?? () => Navigator.of(context).maybePop(),
  60. behavior: HitTestBehavior.opaque,
  61. child: const Center(
  62. child: Icon(
  63. Icons.chevron_left,
  64. size: 22,
  65. color: AppColors.textPrimary,
  66. ),
  67. ),
  68. ),
  69. ),
  70. ),
  71. // 右侧操作按钮 — 绝对定位
  72. if (showRight && rightWidget != null)
  73. Positioned(
  74. right: 0,
  75. top: 0,
  76. bottom: 0,
  77. child: SizedBox(
  78. width: 56,
  79. height: 56,
  80. child: Center(child: rightWidget!),
  81. ),
  82. ),
  83. ],
  84. ),
  85. );
  86. }
  87. @override
  88. Size get preferredSize => const Size.fromHeight(56);
  89. }