title_bar_widget.dart 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import 'package:flutter/material.dart';
  2. import 'package:photos/theme/ente_theme.dart';
  3. import 'package:photos/ui/components/icon_button_widget.dart';
  4. class TitleBarWidget extends StatelessWidget {
  5. final IconButtonWidget? leading;
  6. final String? title;
  7. final String? caption;
  8. final Widget? flexibleSpaceTitle;
  9. final String? flexibleSpaceCaption;
  10. final List<Widget>? actionIcons;
  11. final bool isTitleH2WithoutLeading;
  12. final bool isFlexibleSpaceDisabled;
  13. final bool isOnTopOfScreen;
  14. final Color? backgroundColor;
  15. const TitleBarWidget({
  16. this.leading,
  17. this.title,
  18. this.caption,
  19. this.flexibleSpaceTitle,
  20. this.flexibleSpaceCaption,
  21. this.actionIcons,
  22. this.isTitleH2WithoutLeading = false,
  23. this.isFlexibleSpaceDisabled = false,
  24. this.isOnTopOfScreen = true,
  25. this.backgroundColor,
  26. super.key,
  27. });
  28. @override
  29. Widget build(BuildContext context) {
  30. const toolbarHeight = 48.0;
  31. final textTheme = getEnteTextTheme(context);
  32. final colorTheme = getEnteColorScheme(context);
  33. return SliverAppBar(
  34. backgroundColor: backgroundColor,
  35. primary: isOnTopOfScreen ? true : false,
  36. toolbarHeight: toolbarHeight,
  37. leadingWidth: 48,
  38. automaticallyImplyLeading: false,
  39. pinned: true,
  40. expandedHeight: isFlexibleSpaceDisabled ? toolbarHeight : 102,
  41. centerTitle: false,
  42. titleSpacing: 4,
  43. title: Padding(
  44. padding: EdgeInsets.only(left: isTitleH2WithoutLeading ? 16 : 0),
  45. child: Column(
  46. crossAxisAlignment: CrossAxisAlignment.start,
  47. mainAxisAlignment: MainAxisAlignment.start,
  48. children: [
  49. title == null
  50. ? const SizedBox.shrink()
  51. : Text(
  52. title!,
  53. style: isTitleH2WithoutLeading
  54. ? textTheme.h2Bold
  55. : textTheme.largeBold,
  56. ),
  57. caption == null || isTitleH2WithoutLeading
  58. ? const SizedBox.shrink()
  59. : Text(
  60. caption!,
  61. style: textTheme.mini.copyWith(color: colorTheme.textMuted),
  62. )
  63. ],
  64. ),
  65. ),
  66. actions: [
  67. Padding(
  68. padding: const EdgeInsets.symmetric(horizontal: 4),
  69. child: Row(
  70. children: _actionsWithPaddingInBetween(),
  71. ),
  72. ),
  73. ],
  74. leading: isTitleH2WithoutLeading
  75. ? null
  76. : leading ??
  77. IconButtonWidget(
  78. icon: Icons.arrow_back_outlined,
  79. iconButtonType: IconButtonType.primary,
  80. onTap: () {
  81. Navigator.pop(context);
  82. },
  83. ),
  84. flexibleSpace: isFlexibleSpaceDisabled
  85. ? null
  86. : FlexibleSpaceBar(
  87. background: SafeArea(
  88. child: Column(
  89. crossAxisAlignment: CrossAxisAlignment.start,
  90. mainAxisSize: MainAxisSize.min,
  91. children: <Widget>[
  92. const SizedBox(height: toolbarHeight),
  93. Padding(
  94. padding: const EdgeInsets.symmetric(
  95. vertical: 4,
  96. horizontal: 16,
  97. ),
  98. child: Column(
  99. crossAxisAlignment: CrossAxisAlignment.start,
  100. children: [
  101. flexibleSpaceTitle == null
  102. ? const SizedBox.shrink()
  103. : flexibleSpaceTitle!,
  104. flexibleSpaceCaption == null
  105. ? const SizedBox.shrink()
  106. : Text(
  107. flexibleSpaceCaption!,
  108. style: textTheme.small.copyWith(
  109. color: colorTheme.textMuted,
  110. ),
  111. overflow: TextOverflow.ellipsis,
  112. maxLines: 1,
  113. )
  114. ],
  115. ),
  116. ),
  117. ],
  118. ),
  119. ),
  120. ),
  121. );
  122. }
  123. _actionsWithPaddingInBetween() {
  124. if (actionIcons == null) {
  125. return <Widget>[const SizedBox.shrink()];
  126. }
  127. final actions = <Widget>[];
  128. bool addWhiteSpace = false;
  129. final length = actionIcons!.length;
  130. int index = 0;
  131. if (length == 0) {
  132. return <Widget>[const SizedBox.shrink()];
  133. }
  134. if (length == 1) {
  135. return actionIcons;
  136. }
  137. while (index < length) {
  138. if (!addWhiteSpace) {
  139. actions.add(actionIcons![index]);
  140. index++;
  141. addWhiteSpace = true;
  142. } else {
  143. actions.add(const SizedBox(width: 4));
  144. addWhiteSpace = false;
  145. }
  146. }
  147. return actions;
  148. }
  149. }