screenshots_view.dart 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. import 'package:clean/base/base_page.dart';
  2. import 'package:clean/module/screenshots_blurry/screenshots_controller.dart';
  3. import 'package:clean/resource/assets.gen.dart';
  4. import 'package:clean/router/app_pages.dart';
  5. import 'package:flutter/Material.dart';
  6. import 'package:flutter_screenutil/flutter_screenutil.dart';
  7. import 'package:get/get.dart';
  8. import 'package:wechat_assets_picker/wechat_assets_picker.dart';
  9. class ScreenshotsPage extends BasePage<ScreenShotsController> {
  10. const ScreenshotsPage({super.key});
  11. static void start(String titleName) {
  12. Get.toNamed(RoutePath.screenshots, arguments: {
  13. "titleName": titleName,
  14. });
  15. }
  16. @override
  17. bool statusBarDarkFont() {
  18. return false;
  19. }
  20. @override
  21. bool immersive() {
  22. return true;
  23. }
  24. @override
  25. Widget buildBody(BuildContext context) {
  26. return Stack(children: [
  27. Container(
  28. child: SafeArea(
  29. child: Column(
  30. children: [
  31. _titleCard(),
  32. // Photo groups
  33. Expanded(
  34. child: Obx(() {
  35. return SizedBox(
  36. child: GridView.builder(
  37. padding: EdgeInsets.symmetric(horizontal: 16.w),
  38. scrollDirection: Axis.vertical,
  39. // 设置为垂直方向滚动
  40. physics: BouncingScrollPhysics(),
  41. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  42. crossAxisCount: 3, // 每行显示 2 个元素
  43. mainAxisSpacing: 8.w, // 垂直间距
  44. crossAxisSpacing: 8.h, // 水平间距
  45. ),
  46. itemCount: controller.photoGroups[0].imageCount,
  47. itemBuilder:
  48. _buildPhotoItem(controller.photoGroups[0].title)),
  49. );
  50. }),
  51. ),
  52. _bottomBarCard(),
  53. SizedBox(height: 8.h),
  54. ],
  55. ),
  56. ),
  57. ),
  58. IgnorePointer(
  59. child: Assets.images.bgHome.image(
  60. width: 360.w,
  61. height: 234.h,
  62. ),
  63. ),
  64. ]);
  65. }
  66. Widget _titleCard() {
  67. return Container(
  68. alignment: Alignment.centerLeft,
  69. padding: EdgeInsets.only(left: 16.w, top: 14.h, right: 16.w),
  70. child: Column(
  71. crossAxisAlignment: CrossAxisAlignment.start,
  72. children: [
  73. Row(
  74. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  75. children: [
  76. GestureDetector(
  77. onTap: () => Get.back(),
  78. child: Assets.images.iconBackArrow.image(
  79. width: 28.w,
  80. height: 28.h,
  81. ),
  82. ),
  83. GestureDetector(
  84. onTap: () => controller
  85. .toggleGroupSelection(controller.photoGroups[0].title),
  86. child: Obx(() => Text(
  87. controller.photoGroups
  88. .firstWhere((g) =>
  89. g.title == controller.photoGroups[0].title)
  90. .isSelected
  91. .value
  92. ? 'Deselect All'
  93. : 'Select All',
  94. style: TextStyle(
  95. color: Colors.white.withValues(alpha: 0.7),
  96. fontSize: 14.sp,
  97. fontWeight: FontWeight.w400,
  98. ),
  99. )),
  100. ),
  101. ],
  102. ),
  103. SizedBox(height: 12.h),
  104. Text(
  105. controller.titleName,
  106. style: TextStyle(
  107. color: Colors.white,
  108. fontSize: 24.sp,
  109. fontWeight: FontWeight.w700,
  110. ),
  111. ),
  112. SizedBox(height: 20.h),
  113. ],
  114. ),
  115. );
  116. }
  117. Widget _bottomBarCard() {
  118. return Container(
  119. width: 328.w,
  120. height: 48.h,
  121. decoration: ShapeDecoration(
  122. color: Color(0xFF0279FB),
  123. shape: RoundedRectangleBorder(
  124. borderRadius: BorderRadius.circular(10.r),
  125. ),
  126. ),
  127. padding: EdgeInsets.symmetric(horizontal: 16.w),
  128. child: Row(
  129. mainAxisAlignment: MainAxisAlignment.center,
  130. children: [
  131. Assets.images.iconDelete.image(
  132. width: 18.w,
  133. height: 18.h,
  134. ),
  135. SizedBox(width: 5.w),
  136. Obx(() {
  137. return Text(
  138. '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSize.value.toStringAsFixed(1)} KB)',
  139. textAlign: TextAlign.center,
  140. style: TextStyle(
  141. color: Colors.white,
  142. fontSize: 16.sp,
  143. fontWeight: FontWeight.w500,
  144. ),
  145. );
  146. }),
  147. ],
  148. ),
  149. );
  150. }
  151. Widget Function(BuildContext, int) _buildPhotoItem(String title) =>
  152. (context, index) {
  153. final group =
  154. controller.photoGroups.firstWhere((group) => group.title == title);
  155. final assetEntity = group.images[index];
  156. return GestureDetector(
  157. onTap: () => controller.clickImage(title, index),
  158. child: Obx(() {
  159. final isSelected = group.selectedImages[index];
  160. return Stack(
  161. children: [
  162. Container(
  163. width: 104.w,
  164. height: 104.w,
  165. decoration: ShapeDecoration(
  166. color: Colors.white.withValues(alpha: 0.12),
  167. shape: RoundedRectangleBorder(
  168. borderRadius: BorderRadius.circular(9.27.sp),
  169. ),
  170. image: DecorationImage(
  171. image: AssetEntityImageProvider(assetEntity),
  172. fit: BoxFit.cover,
  173. ),
  174. ),
  175. ),
  176. Positioned(
  177. right: 8.w,
  178. bottom: 8.h,
  179. child: GestureDetector(
  180. onTap: () =>
  181. controller.toggleImageSelection(title, index),
  182. child: Container(
  183. child: isSelected
  184. ? Center(
  185. child: Assets.images.iconSelected.image(
  186. width: 20.w,
  187. height: 20.h,
  188. ),
  189. )
  190. : Center(
  191. child: Assets.images.iconUnselected.image(
  192. width: 20.w,
  193. height: 20.h,
  194. )),
  195. )),
  196. ),
  197. ],
  198. );
  199. }),
  200. );
  201. };
  202. Widget _noNoPicturesCard() {
  203. return Column(
  204. children: [
  205. _titleCard(),
  206. Expanded(
  207. child: Center(
  208. child: Column(
  209. mainAxisAlignment: MainAxisAlignment.center,
  210. crossAxisAlignment: CrossAxisAlignment.center,
  211. children: [
  212. Container(
  213. width: 70.w,
  214. height: 70.h,
  215. clipBehavior: Clip.antiAlias,
  216. decoration: BoxDecoration(),
  217. child: Assets.images.iconNoPictures.image(),
  218. ),
  219. SizedBox(height: 22.h),
  220. Text(
  221. 'No pictures found',
  222. textAlign: TextAlign.center,
  223. style: TextStyle(
  224. color: Colors.white,
  225. fontSize: 20.sp,
  226. fontWeight: FontWeight.w700,
  227. ),
  228. ),
  229. SizedBox(height: 12.h),
  230. Text(
  231. 'No pictures available at the moment',
  232. textAlign: TextAlign.center,
  233. style: TextStyle(
  234. color: Colors.white.withValues(alpha: 0.6),
  235. fontSize: 14.sp,
  236. fontWeight: FontWeight.w400,
  237. ),
  238. ),
  239. ],
  240. ),
  241. ),
  242. ),
  243. ],
  244. );
  245. }
  246. }