title_bar_widget.dart 3.7 KB

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