photo_preview_view.dart 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import 'package:clean/base/base_page.dart';
  2. import 'package:clean/data/bean/photos_type.dart';
  3. import 'package:clean/module/photo_preview/photo_preview_controller.dart';
  4. import 'package:clean/resource/assets.gen.dart';
  5. import 'package:clean/router/app_pages.dart';
  6. import 'package:flutter/Material.dart';
  7. import 'package:flutter/src/widgets/framework.dart';
  8. import 'package:flutter_card_swiper/flutter_card_swiper.dart';
  9. import 'package:flutter_screenutil/flutter_screenutil.dart';
  10. import 'package:get/get.dart';
  11. import 'package:wechat_assets_picker/wechat_assets_picker.dart';
  12. class PhotoPreviewPage extends BasePage<PhotoPreviewController> {
  13. PhotoPreviewPage({Key? key}) : super(key: key);
  14. static void start(PhotosType photosType, String currentImageId) {
  15. print(' PhotoPreviewPage start $photosType $currentImageId');
  16. Get.toNamed(RoutePath.photoPreview, arguments: {
  17. "photosType": photosType,
  18. "currentImageId": currentImageId,
  19. });
  20. }
  21. @override
  22. bool immersive() {
  23. // TODO: implement immersive
  24. return true;
  25. }
  26. @override
  27. bool statusBarDarkFont() {
  28. // TODO: implement statusBarDarkFont
  29. return false;
  30. }
  31. @override
  32. Widget buildBody(BuildContext context) {
  33. return Stack(children: [
  34. Container(
  35. child: SafeArea(
  36. child: Container(
  37. child: Obx(() {
  38. if (controller.isSwiperEnd.value) {
  39. return onSwiperEndCard();
  40. } else {
  41. return _photoDataCard();
  42. }
  43. }),
  44. ),
  45. ),
  46. ),
  47. IgnorePointer(
  48. child: Assets.images.bgHome.image(
  49. width: 360.w,
  50. height: 234.h,
  51. ),
  52. ),
  53. ]);
  54. }
  55. Widget _photoDataCard() {
  56. return Column(
  57. children: [
  58. _titleCard(),
  59. Spacer(),
  60. (controller.photoGroups.length == 1)
  61. ? Container(
  62. width: 314.w,
  63. height: 392.h,
  64. child: AssetEntityImage(
  65. controller.photoGroups[0],
  66. width: 314.w,
  67. height: 392.h,
  68. ),
  69. )
  70. : Container(
  71. width: 314.w,
  72. height: 392.h,
  73. child: CardSwiper(
  74. scale: 0.8,
  75. allowedSwipeDirection: AllowedSwipeDirection.only(
  76. right: true,
  77. left: true,
  78. ),
  79. isLoop: false,
  80. backCardOffset: Offset(0.w, -20.h),
  81. controller: controller.cardSwiperController.value,
  82. cardsCount: controller.photoGroups.length,
  83. onSwipe: controller.onSwipe,
  84. onUndo: controller.onSwiperUndo,
  85. onEnd: controller.onSwiperEnd,
  86. cardBuilder: (context, index, horizontalOffsetPercentage,
  87. verticalOffsetPercentage) {
  88. final assetEntity = controller.photoGroups[index];
  89. return AssetEntityImage(
  90. assetEntity,
  91. width: 314.w,
  92. height: 392.h,
  93. );
  94. },
  95. ),
  96. ),
  97. Spacer(),
  98. bottomButtonCard(),
  99. _bottomBarCard(),
  100. ],
  101. );
  102. }
  103. Widget _titleCard() {
  104. return Container(
  105. alignment: Alignment.centerLeft,
  106. padding: EdgeInsets.only(left: 16.w, top: 14.h, right: 16.w),
  107. child: Column(
  108. crossAxisAlignment: CrossAxisAlignment.start,
  109. children: [
  110. Row(
  111. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  112. children: [
  113. GestureDetector(
  114. onTap: controller.clickBack,
  115. child: Assets.images.iconBackArrow.image(
  116. width: 28.w,
  117. height: 28.h,
  118. ),
  119. ),
  120. Obx(() => Row(
  121. mainAxisAlignment: MainAxisAlignment.center,
  122. children: [
  123. Text(
  124. '${controller.groupIndex.value + 1}',
  125. textAlign: TextAlign.center,
  126. style: TextStyle(
  127. color: Colors.white,
  128. fontSize: 16.sp,
  129. fontWeight: FontWeight.w700,
  130. ),
  131. ),
  132. Text(
  133. ' / ${controller.photoGroups.length}',
  134. textAlign: TextAlign.center,
  135. style: TextStyle(
  136. color: Colors.white.withValues(alpha: 0.6),
  137. fontSize: 16.sp,
  138. fontWeight: FontWeight.w500,
  139. ),
  140. ),
  141. ],
  142. )),
  143. GestureDetector(
  144. onTap: controller.recoverSelectPhoto,
  145. child: Assets.images.iconPreviewRecover.image(
  146. width: 30.w,
  147. height: 30.h,
  148. ),
  149. ),
  150. ],
  151. ),
  152. SizedBox(height: 12.h),
  153. ],
  154. ),
  155. );
  156. }
  157. Widget _bottomBarCard() {
  158. return GestureDetector(
  159. onTap: controller.clickDelete,
  160. child: Container(
  161. width: 360.w,
  162. height: 81.h,
  163. padding: EdgeInsets.symmetric(horizontal: 16.w),
  164. decoration: ShapeDecoration(
  165. color: Color(0xFF23232A),
  166. shape: RoundedRectangleBorder(
  167. side: BorderSide(
  168. width: 1.w, color: Colors.white.withValues(alpha: 0.1)),
  169. borderRadius: BorderRadius.only(
  170. topLeft: Radius.circular(14.r),
  171. topRight: Radius.circular(14.r),
  172. ),
  173. ),
  174. ),
  175. child: Row(
  176. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  177. children: [
  178. Obx(() {
  179. return Text(
  180. '${controller.selectedFileCount.value} files selected (${controller.selectedFilesSize.value.toStringAsFixed(1)} KB)',
  181. textAlign: TextAlign.center,
  182. style: TextStyle(
  183. color: Colors.white.withValues(alpha: 0.9),
  184. fontSize: 13.sp,
  185. fontWeight: FontWeight.w500,
  186. ),
  187. );
  188. }),
  189. Container(
  190. width: 108.w,
  191. height: 38.h,
  192. decoration: ShapeDecoration(
  193. color: Color(0xFF0279FB),
  194. shape: RoundedRectangleBorder(
  195. borderRadius: BorderRadius.circular(10.r),
  196. ),
  197. ),
  198. child: Row(
  199. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  200. children: [
  201. Text(
  202. 'Delete',
  203. textAlign: TextAlign.center,
  204. style: TextStyle(
  205. color: Colors.white,
  206. fontSize: 16.sp,
  207. fontWeight: FontWeight.w500,
  208. ),
  209. ),
  210. Assets.images.iconDelete.image(
  211. width: 18.w,
  212. height: 18.h,
  213. ),
  214. ],
  215. ),
  216. ),
  217. ],
  218. ),
  219. ),
  220. );
  221. }
  222. Widget bottomButtonCard() {
  223. return Container(
  224. margin: EdgeInsets.only(bottom: 54.h),
  225. child: Row(
  226. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  227. children: [
  228. GestureDetector(
  229. onTap: () => controller.clickSelect(),
  230. child: Assets.images.iconPreviewSelect.image(
  231. width: 62.w,
  232. height: 62.h,
  233. ),
  234. ),
  235. GestureDetector(
  236. onTap: () => controller.clickUnselect(),
  237. child: Assets.images.iconPreviewNoSelect.image(
  238. width: 62.w,
  239. height: 62.h,
  240. ),
  241. ),
  242. ],
  243. ),
  244. );
  245. }
  246. Widget onSwiperEndCard() {
  247. return Column(
  248. children: [
  249. Spacer(),
  250. Center(
  251. child: Column(
  252. crossAxisAlignment: CrossAxisAlignment.center,
  253. mainAxisAlignment: MainAxisAlignment.center,
  254. children: [
  255. Text(
  256. 'Perfect!',
  257. textAlign: TextAlign.center,
  258. style: TextStyle(
  259. color: Colors.white,
  260. fontSize: 32.sp,
  261. fontWeight: FontWeight.w700,
  262. ),
  263. ),
  264. SizedBox(height: 16.h),
  265. SizedBox(
  266. child: Row(
  267. mainAxisAlignment: MainAxisAlignment.center,
  268. children: [
  269. Container(
  270. clipBehavior: Clip.antiAlias,
  271. decoration: BoxDecoration(),
  272. child: Assets.images.iconPreviewSwiperEndFirework.image(
  273. width: 40.w,
  274. height: 40.w,
  275. ),
  276. ),
  277. SizedBox(width: 4.w),
  278. Text(
  279. 'All Similar and Redundant\nPhotos Cleared',
  280. textAlign: TextAlign.center,
  281. style: TextStyle(
  282. color: Colors.white.withValues(alpha: 0.9),
  283. fontSize: 16.sp,
  284. fontWeight: FontWeight.w400,
  285. ),
  286. ),
  287. SizedBox(width: 4.w),
  288. Container(
  289. clipBehavior: Clip.antiAlias,
  290. decoration: BoxDecoration(),
  291. child: Assets.images.iconPreviewSwiperEndFirework.image(
  292. width: 40.w,
  293. height: 40.w,
  294. ),
  295. ),
  296. ],
  297. ),
  298. ),
  299. ],
  300. ),
  301. ),
  302. Spacer(),
  303. _bottomBarCard(),
  304. ],
  305. );
  306. }
  307. }