my_appbar.dart 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. import 'package:flutter/cupertino.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:flutter/widgets.dart';
  5. import 'package:cs_resources/generated/assets.dart';
  6. import 'package:cs_resources/constants/color_constants.dart';
  7. import 'package:router/ext/auto_router_extensions.dart';
  8. import 'my_load_image.dart';
  9. import 'search_app_bar.dart';
  10. class MyAppBar {
  11. ///封装的默认的AppBar,Light默认模式下,黑色图标+黑色文本,Dark模式下,白色图标+白色文本
  12. static AppBar appBar(BuildContext context, String title,
  13. {void Function()? backCallback,
  14. String? backIconPath,
  15. double? backIconWidth,
  16. double? backIconHeight,
  17. String? subTitle,
  18. Color? subTitleColor,
  19. Color textColor = Colors.white,
  20. Color backgroundColor = Colors.transparent,
  21. SystemUiOverlayStyle? systemUiOverlayStyle,
  22. List<Widget>? actions}) {
  23. return AppBar(
  24. //设置变色与背景颜色一致,避免滚动的时候AppBar变色
  25. backgroundColor: backgroundColor,
  26. surfaceTintColor: backgroundColor,
  27. systemOverlayStyle: systemUiOverlayStyle,
  28. leading: IconButton(
  29. icon: MyAssetImage(backIconPath ?? Assets.baseLibWhiteBack, width: backIconWidth ?? 11, height: backIconHeight ?? 18),
  30. onPressed: () {
  31. if (backCallback != null) {
  32. backCallback();
  33. } else {
  34. appRouter.maybePop();
  35. }
  36. },
  37. ),
  38. centerTitle: true,
  39. title: subTitle == null
  40. ? Text(
  41. title,
  42. style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w500),
  43. )
  44. : Column(
  45. mainAxisSize: MainAxisSize.max,
  46. mainAxisAlignment: MainAxisAlignment.center,
  47. crossAxisAlignment: CrossAxisAlignment.center,
  48. children: [
  49. Text(
  50. title,
  51. style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w500),
  52. ),
  53. Text(
  54. subTitle,
  55. style: TextStyle(color: subTitleColor ?? Colors.white, fontSize: 15, fontWeight: FontWeight.w400),
  56. )
  57. ],
  58. ),
  59. actions: actions,
  60. elevation: 0.0,
  61. bottom: const PreferredSize(
  62. preferredSize: Size.fromHeight(0.5),
  63. child: Divider(
  64. height: 0.5,
  65. indent: 0.0,
  66. color: ColorConstants.dividerBar,
  67. )),
  68. );
  69. }
  70. //自定义高度快
  71. static SizedBox rowHeight({double height = 30}) {
  72. return SizedBox(height: height);
  73. }
  74. //自定义宽度快
  75. static SizedBox rowWidth({double width = 30}) {
  76. return SizedBox(width: width);
  77. }
  78. /// 带搜索的AppBar
  79. static AppBar appSearchBar(BuildContext context,
  80. {void Function()? backCallback,
  81. String? value,
  82. String? hintText,
  83. Color textColor = Colors.white,
  84. Color backgroundColor = Colors.transparent,
  85. ValueChanged<String>? onSearch,
  86. ValueChanged<String>? onChanged,
  87. SystemUiOverlayStyle? systemUiOverlayStyle,
  88. TextEditingController? controller,
  89. List<Widget>? actions}) {
  90. return AppBar(
  91. backgroundColor: backgroundColor,
  92. surfaceTintColor: backgroundColor,
  93. systemOverlayStyle: systemUiOverlayStyle,
  94. // 标题与其他控件的间隔
  95. titleSpacing: 0,
  96. leading: IconButton(
  97. icon: const MyAssetImage(Assets.baseLibWhiteBack, width: 11, height: 18),
  98. onPressed: () {
  99. if (backCallback != null) {
  100. backCallback();
  101. } else {
  102. appRouter.maybePop();
  103. }
  104. },
  105. ),
  106. centerTitle: true,
  107. title: SearchAppBar(
  108. onSearch: onSearch,
  109. onChanged: onChanged,
  110. value: value,
  111. hintText: hintText,
  112. controller: controller,
  113. ),
  114. actions: actions,
  115. elevation: 0.0,
  116. bottom: const PreferredSize(
  117. preferredSize: Size.fromHeight(0.5),
  118. child: Divider(
  119. height: 0.5,
  120. indent: 0.0,
  121. color: ColorConstants.dividerBar,
  122. )),
  123. );
  124. }
  125. /// 当前App中的自定义TitleBar用于沉浸式处理,不是用在 Scaffold 下面的,直接放在 Column 下面即可
  126. static Widget titleBar(
  127. BuildContext context,
  128. String title, {
  129. void Function()? backCallback,
  130. String? backIconPath,
  131. double? backIconWidth,
  132. double? backIconHeight,
  133. String? subTitle,
  134. Color? subTitleColor,
  135. bool needBottomDivider = true,
  136. Color textColor = Colors.white,
  137. Color backgroundColor = Colors.transparent,
  138. List<Widget>? actions,
  139. }) {
  140. // 计算左侧和右侧固定容器的宽度
  141. double sideWidth = 55;
  142. return Column(
  143. children: [
  144. Container(
  145. height: kToolbarHeight,
  146. color: backgroundColor,
  147. child: Stack(
  148. children: [
  149. // 返回图标在左侧
  150. Positioned(
  151. left: 0,
  152. top: 0,
  153. bottom: 0,
  154. child: Container(
  155. width: sideWidth,
  156. alignment: Alignment.center,
  157. child: IconButton(
  158. icon: MyAssetImage(
  159. backIconPath ?? Assets.baseLibWhiteBack,
  160. width: backIconWidth ?? 11,
  161. height: backIconHeight ?? 18,
  162. ),
  163. onPressed: () {
  164. if (backCallback != null) {
  165. backCallback();
  166. } else {
  167. appRouter.maybePop();
  168. }
  169. },
  170. ),
  171. ),
  172. ),
  173. // 标题在中间
  174. Positioned.fill(
  175. child: Center(
  176. child: ConstrainedBox(
  177. constraints: BoxConstraints(
  178. maxWidth: MediaQuery.of(context).size.width - 2 * sideWidth,
  179. ),
  180. child: subTitle == null
  181. ? Text(
  182. title,
  183. style: TextStyle(color: textColor, fontSize: 18, fontWeight: FontWeight.w500),
  184. overflow: TextOverflow.ellipsis,
  185. )
  186. : Column(
  187. mainAxisSize: MainAxisSize.min,
  188. mainAxisAlignment: MainAxisAlignment.center,
  189. crossAxisAlignment: CrossAxisAlignment.center,
  190. children: [
  191. Text(
  192. title,
  193. style: TextStyle(color: textColor, fontSize: 18, fontWeight: FontWeight.w500),
  194. overflow: TextOverflow.ellipsis,
  195. ),
  196. Text(
  197. subTitle!,
  198. style: TextStyle(color: subTitleColor ?? textColor, fontSize: 15, fontWeight: FontWeight.w400),
  199. ),
  200. ],
  201. ),
  202. ),
  203. ),
  204. ),
  205. // 右侧的操作按钮
  206. Positioned(
  207. right: 0,
  208. top: 0,
  209. bottom: 0,
  210. child: Container(
  211. alignment: Alignment.centerRight,
  212. child: Row(
  213. mainAxisSize: MainAxisSize.min,
  214. children: actions ?? [SizedBox(width: sideWidth)],
  215. ),
  216. ),
  217. ),
  218. ],
  219. ),
  220. ),
  221. // 底部的分割线
  222. if (needBottomDivider)
  223. Divider(
  224. height: 0.5,
  225. color: ColorConstants.dividerBar,
  226. ),
  227. ],
  228. );
  229. }
  230. /// 当前App中的自定义TitleBar用于沉浸式处理,不是用在 Scaffold 下面的,直接放在 Column 下面即可
  231. static Widget searchTitleBar(BuildContext context, {
  232. void Function()? backCallback,
  233. String? value,
  234. String? hintText,
  235. Color textColor = Colors.white,
  236. Color backgroundColor = Colors.transparent,
  237. ValueChanged<String>? onSearch,
  238. ValueChanged<String>? onChanged,
  239. bool needBottomDivider = true,
  240. TextEditingController? controller,
  241. List<Widget>? actions,
  242. }) {
  243. return Column(
  244. children: [
  245. Container(
  246. height: kToolbarHeight,
  247. color: backgroundColor,
  248. child: Row(
  249. crossAxisAlignment: CrossAxisAlignment.center,
  250. children: [
  251. // 返回图标
  252. Container(
  253. width: 55,
  254. alignment: Alignment.center,
  255. child: IconButton(
  256. icon: MyAssetImage(
  257. Assets.baseLibWhiteBack,
  258. width: 11,
  259. height: 18,
  260. ),
  261. onPressed: () {
  262. if (backCallback != null) {
  263. backCallback();
  264. } else {
  265. appRouter.maybePop();
  266. }
  267. },
  268. ),
  269. ),
  270. // 搜索栏
  271. Expanded(
  272. child: SearchAppBar(
  273. onSearch: onSearch,
  274. onChanged: onChanged,
  275. value: value,
  276. hintText: hintText,
  277. controller: controller,
  278. ),
  279. ),
  280. // 右侧操作按钮
  281. Container(
  282. alignment: Alignment.centerRight,
  283. child: Row(
  284. mainAxisSize: MainAxisSize.min,
  285. children: actions ?? [],
  286. ),
  287. ),
  288. ],
  289. ),
  290. ),
  291. // 底部的分割线
  292. if (needBottomDivider)
  293. const Divider(
  294. height: 0.5,
  295. indent: 0.0,
  296. color: ColorConstants.dividerBar,
  297. ),
  298. ],
  299. );
  300. }
  301. }