photo_preview_view.dart 11 KB

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