TZPhotoPreviewController.m 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. //
  2. // TZPhotoPreviewController.m
  3. // TZImagePickerController
  4. //
  5. // Created by 谭真 on 15/12/24.
  6. // Copyright © 2015年 谭真. All rights reserved.
  7. //
  8. #import "TZPhotoPreviewController.h"
  9. #import "TZPhotoPreviewCell.h"
  10. #import "TZAssetModel.h"
  11. #import "UIView+Layout.h"
  12. #import "TZImagePickerController.h"
  13. #import "TZImageManager.h"
  14. #import "TZImageCropManager.h"
  15. @interface TZPhotoPreviewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UIScrollViewDelegate> {
  16. UICollectionView *_collectionView;
  17. UICollectionViewFlowLayout *_layout;
  18. NSArray *_photosTemp;
  19. NSArray *_assetsTemp;
  20. UIView *_naviBar;
  21. UIButton *_backButton;
  22. UIButton *_selectButton;
  23. UILabel *_indexLabel;
  24. UIView *_toolBar;
  25. UIButton *_doneButton;
  26. UIImageView *_numberImageView;
  27. UILabel *_numberLabel;
  28. UIButton *_originalPhotoButton;
  29. UILabel *_originalPhotoLabel;
  30. CGFloat _offsetItemCount;
  31. BOOL _didSetIsSelectOriginalPhoto;
  32. }
  33. @property (nonatomic, assign) BOOL isHideNaviBar;
  34. @property (nonatomic, strong) UIView *cropBgView;
  35. @property (nonatomic, strong) UIView *cropView;
  36. @property (nonatomic, assign) double progress;
  37. @property (strong, nonatomic) UIAlertController *alertView;
  38. @end
  39. @implementation TZPhotoPreviewController
  40. - (void)viewDidLoad {
  41. [super viewDidLoad];
  42. [TZImageManager manager].shouldFixOrientation = YES;
  43. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  44. if (!_didSetIsSelectOriginalPhoto) {
  45. _isSelectOriginalPhoto = _tzImagePickerVc.isSelectOriginalPhoto;
  46. }
  47. if (!self.models.count) {
  48. self.models = [NSMutableArray arrayWithArray:_tzImagePickerVc.selectedModels];
  49. _assetsTemp = [NSMutableArray arrayWithArray:_tzImagePickerVc.selectedAssets];
  50. }
  51. [self configCollectionView];
  52. [self configCustomNaviBar];
  53. [self configBottomToolBar];
  54. self.view.clipsToBounds = YES;
  55. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeStatusBarOrientationNotification:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
  56. }
  57. - (void)setIsSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto {
  58. _isSelectOriginalPhoto = isSelectOriginalPhoto;
  59. _didSetIsSelectOriginalPhoto = YES;
  60. }
  61. - (void)setPhotos:(NSMutableArray *)photos {
  62. _photos = photos;
  63. _photosTemp = [NSArray arrayWithArray:photos];
  64. }
  65. - (void)viewWillAppear:(BOOL)animated {
  66. [super viewWillAppear:animated];
  67. [self.navigationController setNavigationBarHidden:YES animated:YES];
  68. [UIApplication sharedApplication].statusBarHidden = YES;
  69. if (_currentIndex) {
  70. [_collectionView setContentOffset:CGPointMake((self.view.tz_width + 20) * self.currentIndex, 0) animated:NO];
  71. }
  72. [self refreshNaviBarAndBottomBarState];
  73. }
  74. - (void)viewWillDisappear:(BOOL)animated {
  75. [super viewWillDisappear:animated];
  76. TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  77. if (tzImagePickerVc.needShowStatusBar) {
  78. [UIApplication sharedApplication].statusBarHidden = NO;
  79. }
  80. [self.navigationController setNavigationBarHidden:NO animated:YES];
  81. [TZImageManager manager].shouldFixOrientation = NO;
  82. }
  83. - (BOOL)prefersStatusBarHidden {
  84. return YES;
  85. }
  86. - (void)configCustomNaviBar {
  87. TZImagePickerController *tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  88. _naviBar = [[UIView alloc] initWithFrame:CGRectZero];
  89. _naviBar.backgroundColor = [UIColor colorWithRed:(34/255.0) green:(34/255.0) blue:(34/255.0) alpha:0.7];
  90. _backButton = [[UIButton alloc] initWithFrame:CGRectZero];
  91. [_backButton setImage:[UIImage tz_imageNamedFromMyBundle:@"navi_back"] forState:UIControlStateNormal];
  92. [_backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  93. [_backButton addTarget:self action:@selector(backButtonClick) forControlEvents:UIControlEventTouchUpInside];
  94. _selectButton = [[UIButton alloc] initWithFrame:CGRectZero];
  95. [_selectButton setImage:tzImagePickerVc.photoDefImage forState:UIControlStateNormal];
  96. [_selectButton setImage:tzImagePickerVc.photoSelImage forState:UIControlStateSelected];
  97. _selectButton.imageView.clipsToBounds = YES;
  98. _selectButton.imageEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 0);
  99. _selectButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
  100. [_selectButton addTarget:self action:@selector(select:) forControlEvents:UIControlEventTouchUpInside];
  101. _selectButton.hidden = !tzImagePickerVc.showSelectBtn;
  102. _indexLabel = [[UILabel alloc] init];
  103. _indexLabel.font = [UIFont systemFontOfSize:14];
  104. _indexLabel.textColor = [UIColor whiteColor];
  105. _indexLabel.textAlignment = NSTextAlignmentCenter;
  106. [_naviBar addSubview:_selectButton];
  107. [_naviBar addSubview:_indexLabel];
  108. [_naviBar addSubview:_backButton];
  109. [self.view addSubview:_naviBar];
  110. }
  111. - (void)configBottomToolBar {
  112. _toolBar = [[UIView alloc] initWithFrame:CGRectZero];
  113. static CGFloat rgb = 34 / 255.0;
  114. _toolBar.backgroundColor = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:0.7];
  115. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  116. if (_tzImagePickerVc.allowPickingOriginalPhoto) {
  117. _originalPhotoButton = [UIButton buttonWithType:UIButtonTypeCustom];
  118. _originalPhotoButton.imageEdgeInsets = UIEdgeInsetsMake(0, [TZCommonTools tz_isRightToLeftLayout] ? 10 : -10, 0, 0);
  119. _originalPhotoButton.backgroundColor = [UIColor clearColor];
  120. [_originalPhotoButton addTarget:self action:@selector(originalPhotoButtonClick) forControlEvents:UIControlEventTouchUpInside];
  121. _originalPhotoButton.titleLabel.font = [UIFont systemFontOfSize:13];
  122. [_originalPhotoButton setTitle:_tzImagePickerVc.fullImageBtnTitleStr forState:UIControlStateNormal];
  123. [_originalPhotoButton setTitle:_tzImagePickerVc.fullImageBtnTitleStr forState:UIControlStateSelected];
  124. [_originalPhotoButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
  125. [_originalPhotoButton setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
  126. [_originalPhotoButton setImage:_tzImagePickerVc.photoPreviewOriginDefImage forState:UIControlStateNormal];
  127. [_originalPhotoButton setImage:_tzImagePickerVc.photoOriginSelImage forState:UIControlStateSelected];
  128. _originalPhotoLabel = [[UILabel alloc] init];
  129. _originalPhotoLabel.textAlignment = NSTextAlignmentLeft;
  130. _originalPhotoLabel.font = [UIFont systemFontOfSize:13];
  131. _originalPhotoLabel.textColor = [UIColor whiteColor];
  132. _originalPhotoLabel.backgroundColor = [UIColor clearColor];
  133. if (_isSelectOriginalPhoto) [self showPhotoBytes];
  134. }
  135. _doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
  136. _doneButton.titleLabel.font = [UIFont systemFontOfSize:16];
  137. [_doneButton addTarget:self action:@selector(doneButtonClick) forControlEvents:UIControlEventTouchUpInside];
  138. [_doneButton setTitle:_tzImagePickerVc.doneBtnTitleStr forState:UIControlStateNormal];
  139. [_doneButton setTitleColor:_tzImagePickerVc.oKButtonTitleColorNormal forState:UIControlStateNormal];
  140. _numberImageView = [[UIImageView alloc] initWithImage:_tzImagePickerVc.photoNumberIconImage];
  141. _numberImageView.backgroundColor = [UIColor clearColor];
  142. _numberImageView.clipsToBounds = YES;
  143. _numberImageView.contentMode = UIViewContentModeScaleAspectFit;
  144. _numberImageView.hidden = _tzImagePickerVc.selectedModels.count <= 0;
  145. _numberLabel = [[UILabel alloc] init];
  146. _numberLabel.font = [UIFont systemFontOfSize:15];
  147. _numberLabel.textColor = [UIColor whiteColor];
  148. _numberLabel.textAlignment = NSTextAlignmentCenter;
  149. _numberLabel.text = [NSString stringWithFormat:@"%zd",_tzImagePickerVc.selectedModels.count];
  150. _numberLabel.hidden = _tzImagePickerVc.selectedModels.count <= 0;
  151. _numberLabel.backgroundColor = [UIColor clearColor];
  152. [_originalPhotoButton addSubview:_originalPhotoLabel];
  153. [_toolBar addSubview:_doneButton];
  154. [_toolBar addSubview:_originalPhotoButton];
  155. [_toolBar addSubview:_numberImageView];
  156. [_toolBar addSubview:_numberLabel];
  157. [self.view addSubview:_toolBar];
  158. if (_tzImagePickerVc.photoPreviewPageUIConfigBlock) {
  159. _tzImagePickerVc.photoPreviewPageUIConfigBlock(_collectionView, _naviBar, _backButton, _selectButton, _indexLabel, _toolBar, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel);
  160. }
  161. }
  162. - (void)configCollectionView {
  163. _layout = [[UICollectionViewFlowLayout alloc] init];
  164. _layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  165. _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout];
  166. _collectionView.backgroundColor = [UIColor blackColor];
  167. _collectionView.dataSource = self;
  168. _collectionView.delegate = self;
  169. _collectionView.pagingEnabled = YES;
  170. _collectionView.scrollsToTop = NO;
  171. _collectionView.showsHorizontalScrollIndicator = NO;
  172. _collectionView.contentOffset = CGPointMake(0, 0);
  173. _collectionView.contentSize = CGSizeMake(self.models.count * (self.view.tz_width + 20), 0);
  174. [self.view addSubview:_collectionView];
  175. [_collectionView registerClass:[TZPhotoPreviewCell class] forCellWithReuseIdentifier:@"TZPhotoPreviewCell"];
  176. [_collectionView registerClass:[TZVideoPreviewCell class] forCellWithReuseIdentifier:@"TZVideoPreviewCell"];
  177. [_collectionView registerClass:[TZGifPreviewCell class] forCellWithReuseIdentifier:@"TZGifPreviewCell"];
  178. }
  179. - (void)configCropView {
  180. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  181. if (_tzImagePickerVc.maxImagesCount <= 1 && _tzImagePickerVc.allowCrop && _tzImagePickerVc.allowPickingImage) {
  182. [_cropView removeFromSuperview];
  183. [_cropBgView removeFromSuperview];
  184. _cropBgView = [UIView new];
  185. _cropBgView.userInteractionEnabled = NO;
  186. _cropBgView.frame = self.view.bounds;
  187. _cropBgView.backgroundColor = [UIColor clearColor];
  188. [self.view addSubview:_cropBgView];
  189. [TZImageCropManager overlayClippingWithView:_cropBgView cropRect:_tzImagePickerVc.cropRect containerView:self.view needCircleCrop:_tzImagePickerVc.needCircleCrop];
  190. _cropView = [UIView new];
  191. _cropView.userInteractionEnabled = NO;
  192. _cropView.frame = _tzImagePickerVc.cropRect;
  193. _cropView.backgroundColor = [UIColor clearColor];
  194. _cropView.layer.borderColor = [UIColor whiteColor].CGColor;
  195. _cropView.layer.borderWidth = 1.0;
  196. if (_tzImagePickerVc.needCircleCrop) {
  197. _cropView.layer.cornerRadius = _tzImagePickerVc.cropRect.size.width / 2;
  198. _cropView.clipsToBounds = YES;
  199. }
  200. [self.view addSubview:_cropView];
  201. if (_tzImagePickerVc.cropViewSettingBlock) {
  202. _tzImagePickerVc.cropViewSettingBlock(_cropView);
  203. }
  204. [self.view bringSubviewToFront:_naviBar];
  205. [self.view bringSubviewToFront:_toolBar];
  206. }
  207. }
  208. #pragma mark - Layout
  209. - (void)viewDidLayoutSubviews {
  210. [super viewDidLayoutSubviews];
  211. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  212. CGFloat statusBarHeight = [TZCommonTools tz_statusBarHeight];
  213. CGFloat statusBarHeightInterval = statusBarHeight - 20;
  214. CGFloat naviBarHeight = statusBarHeight + _tzImagePickerVc.navigationBar.tz_height;
  215. _naviBar.frame = CGRectMake(0, 0, self.view.tz_width, naviBarHeight);
  216. _backButton.frame = CGRectMake(10, 10 + statusBarHeightInterval, 44, 44);
  217. _selectButton.frame = CGRectMake(self.view.tz_width - 56, 10 + statusBarHeightInterval, 44, 44);
  218. _indexLabel.frame = _selectButton.frame;
  219. _layout.itemSize = CGSizeMake(self.view.tz_width + 20, self.view.tz_height);
  220. _layout.minimumInteritemSpacing = 0;
  221. _layout.minimumLineSpacing = 0;
  222. _collectionView.frame = CGRectMake(-10, 0, self.view.tz_width + 20, self.view.tz_height);
  223. [_collectionView setCollectionViewLayout:_layout];
  224. if (_offsetItemCount > 0) {
  225. CGFloat offsetX = _offsetItemCount * _layout.itemSize.width;
  226. [_collectionView setContentOffset:CGPointMake(offsetX, 0)];
  227. }
  228. if (_tzImagePickerVc.allowCrop) {
  229. [_collectionView reloadData];
  230. }
  231. CGFloat toolBarHeight = [TZCommonTools tz_isIPhoneX] ? 44 + (83 - 49) : 44;
  232. CGFloat toolBarTop = self.view.tz_height - toolBarHeight;
  233. _toolBar.frame = CGRectMake(0, toolBarTop, self.view.tz_width, toolBarHeight);
  234. if (_tzImagePickerVc.allowPickingOriginalPhoto) {
  235. CGFloat fullImageWidth = [_tzImagePickerVc.fullImageBtnTitleStr boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size.width;
  236. _originalPhotoButton.frame = CGRectMake(0, 0, fullImageWidth + 56, 44);
  237. _originalPhotoLabel.frame = CGRectMake(fullImageWidth + 42, 0, 80, 44);
  238. }
  239. [_doneButton sizeToFit];
  240. _doneButton.frame = CGRectMake(self.view.tz_width - _doneButton.tz_width - 12, 0, _doneButton.tz_width, 44);
  241. _numberImageView.frame = CGRectMake(_doneButton.tz_left - 24 - 5, 10, 24, 24);
  242. _numberLabel.frame = _numberImageView.frame;
  243. [self configCropView];
  244. if (_tzImagePickerVc.photoPreviewPageDidLayoutSubviewsBlock) {
  245. _tzImagePickerVc.photoPreviewPageDidLayoutSubviewsBlock(_collectionView, _naviBar, _backButton, _selectButton, _indexLabel, _toolBar, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel);
  246. }
  247. }
  248. #pragma mark - Notification
  249. - (void)didChangeStatusBarOrientationNotification:(NSNotification *)noti {
  250. _offsetItemCount = _collectionView.contentOffset.x / _layout.itemSize.width;
  251. }
  252. #pragma mark - Click Event
  253. - (void)select:(UIButton *)selectButton {
  254. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  255. TZAssetModel *model = _models[self.currentIndex];
  256. if (!selectButton.isSelected) {
  257. // 1. select:check if over the maxImagesCount / 选择照片,检查是否超过了最大个数的限制
  258. if (_tzImagePickerVc.selectedModels.count >= _tzImagePickerVc.maxImagesCount) {
  259. NSString *title = [NSString stringWithFormat:[NSBundle tz_localizedStringForKey:@"Select a maximum of %zd photos"], _tzImagePickerVc.maxImagesCount];
  260. [_tzImagePickerVc showAlertWithTitle:title];
  261. return;
  262. // 2. if not over the maxImagesCount / 如果没有超过最大个数限制
  263. } else {
  264. [_tzImagePickerVc addSelectedModel:model];
  265. if (self.photos) {
  266. [_tzImagePickerVc.selectedAssets addObject:_assetsTemp[self.currentIndex]];
  267. [self.photos addObject:_photosTemp[self.currentIndex]];
  268. }
  269. if (model.type == TZAssetModelMediaTypeVideo && !_tzImagePickerVc.allowPickingMultipleVideo) {
  270. [_tzImagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Select the video when in multi state, we will handle the video as a photo"]];
  271. }
  272. }
  273. } else {
  274. NSArray *selectedModels = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels];
  275. for (TZAssetModel *model_item in selectedModels) {
  276. if ([model.asset.localIdentifier isEqualToString:model_item.asset.localIdentifier]) {
  277. // 1.6.7版本更新:防止有多个一样的model,一次性被移除了
  278. NSArray *selectedModelsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedModels];
  279. for (NSInteger i = 0; i < selectedModelsTmp.count; i++) {
  280. TZAssetModel *model = selectedModelsTmp[i];
  281. if ([model isEqual:model_item]) {
  282. [_tzImagePickerVc removeSelectedModel:model];
  283. // [_tzImagePickerVc.selectedModels removeObjectAtIndex:i];
  284. break;
  285. }
  286. }
  287. if (self.photos) {
  288. // 1.6.7版本更新:防止有多个一样的asset,一次性被移除了
  289. NSArray *selectedAssetsTmp = [NSArray arrayWithArray:_tzImagePickerVc.selectedAssets];
  290. for (NSInteger i = 0; i < selectedAssetsTmp.count; i++) {
  291. id asset = selectedAssetsTmp[i];
  292. if ([asset isEqual:_assetsTemp[self.currentIndex]]) {
  293. [_tzImagePickerVc.selectedAssets removeObjectAtIndex:i];
  294. break;
  295. }
  296. }
  297. // [_tzImagePickerVc.selectedAssets removeObject:_assetsTemp[self.currentIndex]];
  298. [self.photos removeObject:_photosTemp[self.currentIndex]];
  299. }
  300. break;
  301. }
  302. }
  303. }
  304. model.isSelected = !selectButton.isSelected;
  305. [self refreshNaviBarAndBottomBarState];
  306. if (model.isSelected) {
  307. [UIView showOscillatoryAnimationWithLayer:selectButton.imageView.layer type:TZOscillatoryAnimationToBigger];
  308. }
  309. [UIView showOscillatoryAnimationWithLayer:_numberImageView.layer type:TZOscillatoryAnimationToSmaller];
  310. }
  311. - (void)backButtonClick {
  312. if (self.navigationController.childViewControllers.count < 2) {
  313. [self.navigationController dismissViewControllerAnimated:YES completion:nil];
  314. if ([self.navigationController isKindOfClass: [TZImagePickerController class]]) {
  315. TZImagePickerController *nav = (TZImagePickerController *)self.navigationController;
  316. if (nav.imagePickerControllerDidCancelHandle) {
  317. nav.imagePickerControllerDidCancelHandle();
  318. }
  319. }
  320. return;
  321. }
  322. [self.navigationController popViewControllerAnimated:YES];
  323. if (self.backButtonClickBlock) {
  324. self.backButtonClickBlock(_isSelectOriginalPhoto);
  325. }
  326. }
  327. - (void)doneButtonClick {
  328. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  329. // 如果图片正在从iCloud同步中,提醒用户
  330. if (_progress > 0 && _progress < 1 && (_selectButton.isSelected || !_tzImagePickerVc.selectedModels.count )) {
  331. _alertView = [_tzImagePickerVc showAlertWithTitle:[NSBundle tz_localizedStringForKey:@"Synchronizing photos from iCloud"]];
  332. return;
  333. }
  334. // 如果没有选中过照片 点击确定时选中当前预览的照片
  335. if (_tzImagePickerVc.selectedModels.count == 0 && _tzImagePickerVc.minImagesCount <= 0) {
  336. TZAssetModel *model = _models[self.currentIndex];
  337. [_tzImagePickerVc addSelectedModel:model];
  338. }
  339. NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.currentIndex inSection:0];
  340. TZPhotoPreviewCell *cell = (TZPhotoPreviewCell *)[_collectionView cellForItemAtIndexPath:indexPath];
  341. if (_tzImagePickerVc.allowCrop && [cell isKindOfClass:[TZPhotoPreviewCell class]]) { // 裁剪状态
  342. _doneButton.enabled = NO;
  343. [_tzImagePickerVc showProgressHUD];
  344. UIImage *cropedImage = [TZImageCropManager cropImageView:cell.previewView.imageView toRect:_tzImagePickerVc.cropRect zoomScale:cell.previewView.scrollView.zoomScale containerView:self.view];
  345. if (_tzImagePickerVc.needCircleCrop) {
  346. cropedImage = [TZImageCropManager circularClipImage:cropedImage];
  347. }
  348. _doneButton.enabled = YES;
  349. [_tzImagePickerVc hideProgressHUD];
  350. if (self.doneButtonClickBlockCropMode) {
  351. TZAssetModel *model = _models[self.currentIndex];
  352. self.doneButtonClickBlockCropMode(cropedImage,model.asset);
  353. }
  354. } else if (self.doneButtonClickBlock) { // 非裁剪状态
  355. self.doneButtonClickBlock(_isSelectOriginalPhoto);
  356. }
  357. if (self.doneButtonClickBlockWithPreviewType) {
  358. self.doneButtonClickBlockWithPreviewType(self.photos,_tzImagePickerVc.selectedAssets,self.isSelectOriginalPhoto);
  359. }
  360. }
  361. - (void)originalPhotoButtonClick {
  362. _originalPhotoButton.selected = !_originalPhotoButton.isSelected;
  363. _isSelectOriginalPhoto = _originalPhotoButton.isSelected;
  364. _originalPhotoLabel.hidden = !_originalPhotoButton.isSelected;
  365. if (_isSelectOriginalPhoto) {
  366. [self showPhotoBytes];
  367. if (!_selectButton.isSelected) {
  368. // 如果当前已选择照片张数 < 最大可选张数 && 最大可选张数大于1,就选中该张图
  369. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  370. if (_tzImagePickerVc.selectedModels.count < _tzImagePickerVc.maxImagesCount && _tzImagePickerVc.showSelectBtn) {
  371. [self select:_selectButton];
  372. }
  373. }
  374. }
  375. }
  376. - (void)didTapPreviewCell {
  377. self.isHideNaviBar = !self.isHideNaviBar;
  378. _naviBar.hidden = self.isHideNaviBar;
  379. _toolBar.hidden = self.isHideNaviBar;
  380. }
  381. #pragma mark - UIScrollViewDelegate
  382. - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  383. CGFloat offSetWidth = scrollView.contentOffset.x;
  384. offSetWidth = offSetWidth + ((self.view.tz_width + 20) * 0.5);
  385. NSInteger currentIndex = offSetWidth / (self.view.tz_width + 20);
  386. if (currentIndex < _models.count && _currentIndex != currentIndex) {
  387. _currentIndex = currentIndex;
  388. [self refreshNaviBarAndBottomBarState];
  389. }
  390. [[NSNotificationCenter defaultCenter] postNotificationName:@"photoPreviewCollectionViewDidScroll" object:nil];
  391. }
  392. #pragma mark - UICollectionViewDataSource && Delegate
  393. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  394. return _models.count;
  395. }
  396. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  397. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  398. TZAssetModel *model = _models[indexPath.item];
  399. TZAssetPreviewCell *cell;
  400. __weak typeof(self) weakSelf = self;
  401. if (_tzImagePickerVc.allowPickingMultipleVideo && model.type == TZAssetModelMediaTypeVideo) {
  402. cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZVideoPreviewCell" forIndexPath:indexPath];
  403. } else if (_tzImagePickerVc.allowPickingMultipleVideo && model.type == TZAssetModelMediaTypePhotoGif && _tzImagePickerVc.allowPickingGif) {
  404. cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZGifPreviewCell" forIndexPath:indexPath];
  405. } else {
  406. cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZPhotoPreviewCell" forIndexPath:indexPath];
  407. TZPhotoPreviewCell *photoPreviewCell = (TZPhotoPreviewCell *)cell;
  408. photoPreviewCell.cropRect = _tzImagePickerVc.cropRect;
  409. photoPreviewCell.allowCrop = _tzImagePickerVc.allowCrop;
  410. photoPreviewCell.scaleAspectFillCrop = _tzImagePickerVc.scaleAspectFillCrop;
  411. __weak typeof(_tzImagePickerVc) weakTzImagePickerVc = _tzImagePickerVc;
  412. __weak typeof(_collectionView) weakCollectionView = _collectionView;
  413. __weak typeof(photoPreviewCell) weakCell = photoPreviewCell;
  414. [photoPreviewCell setImageProgressUpdateBlock:^(double progress) {
  415. __strong typeof(weakSelf) strongSelf = weakSelf;
  416. __strong typeof(weakTzImagePickerVc) strongTzImagePickerVc = weakTzImagePickerVc;
  417. __strong typeof(weakCollectionView) strongCollectionView = weakCollectionView;
  418. __strong typeof(weakCell) strongCell = weakCell;
  419. strongSelf.progress = progress;
  420. if (progress >= 1) {
  421. if (strongSelf.isSelectOriginalPhoto) [strongSelf showPhotoBytes];
  422. if (strongSelf.alertView && [strongCollectionView.visibleCells containsObject:strongCell]) {
  423. [strongTzImagePickerVc hideAlertView:strongSelf.alertView];
  424. strongSelf.alertView = nil;
  425. [strongSelf doneButtonClick];
  426. }
  427. }
  428. }];
  429. }
  430. cell.model = model;
  431. [cell setSingleTapGestureBlock:^{
  432. __strong typeof(weakSelf) strongSelf = weakSelf;
  433. [strongSelf didTapPreviewCell];
  434. }];
  435. return cell;
  436. }
  437. - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
  438. if ([cell isKindOfClass:[TZPhotoPreviewCell class]]) {
  439. [(TZPhotoPreviewCell *)cell recoverSubviews];
  440. }
  441. }
  442. - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
  443. if ([cell isKindOfClass:[TZPhotoPreviewCell class]]) {
  444. [(TZPhotoPreviewCell *)cell recoverSubviews];
  445. } else if ([cell isKindOfClass:[TZVideoPreviewCell class]]) {
  446. TZVideoPreviewCell *videoCell = (TZVideoPreviewCell *)cell;
  447. if (videoCell.player && videoCell.player.rate != 0.0) {
  448. [videoCell pausePlayerAndShowNaviBar];
  449. }
  450. }
  451. }
  452. #pragma mark - Private Method
  453. - (void)dealloc {
  454. // NSLog(@"%@ dealloc",NSStringFromClass(self.class));
  455. }
  456. - (void)refreshNaviBarAndBottomBarState {
  457. TZImagePickerController *_tzImagePickerVc = (TZImagePickerController *)self.navigationController;
  458. TZAssetModel *model = _models[self.currentIndex];
  459. _selectButton.selected = model.isSelected;
  460. [self refreshSelectButtonImageViewContentMode];
  461. if (_selectButton.isSelected && _tzImagePickerVc.showSelectedIndex && _tzImagePickerVc.showSelectBtn) {
  462. NSString *index = [NSString stringWithFormat:@"%d", (int)([_tzImagePickerVc.selectedAssetIds indexOfObject:model.asset.localIdentifier] + 1)];
  463. _indexLabel.text = index;
  464. _indexLabel.hidden = NO;
  465. } else {
  466. _indexLabel.hidden = YES;
  467. }
  468. _numberLabel.text = [NSString stringWithFormat:@"%zd",_tzImagePickerVc.selectedModels.count];
  469. _numberImageView.hidden = (_tzImagePickerVc.selectedModels.count <= 0 || _isHideNaviBar || _isCropImage);
  470. _numberLabel.hidden = (_tzImagePickerVc.selectedModels.count <= 0 || _isHideNaviBar || _isCropImage);
  471. _originalPhotoButton.selected = _isSelectOriginalPhoto;
  472. _originalPhotoLabel.hidden = !_originalPhotoButton.isSelected;
  473. if (_isSelectOriginalPhoto) [self showPhotoBytes];
  474. // If is previewing video, hide original photo button
  475. // 如果正在预览的是视频,隐藏原图按钮
  476. if (!_isHideNaviBar) {
  477. if (model.type == TZAssetModelMediaTypeVideo) {
  478. _originalPhotoButton.hidden = YES;
  479. _originalPhotoLabel.hidden = YES;
  480. } else {
  481. _originalPhotoButton.hidden = NO;
  482. if (_isSelectOriginalPhoto) _originalPhotoLabel.hidden = NO;
  483. }
  484. }
  485. _doneButton.hidden = NO;
  486. _selectButton.hidden = !_tzImagePickerVc.showSelectBtn;
  487. // 让宽度/高度小于 最小可选照片尺寸 的图片不能选中
  488. if (![[TZImageManager manager] isPhotoSelectableWithAsset:model.asset]) {
  489. _numberLabel.hidden = YES;
  490. _numberImageView.hidden = YES;
  491. _selectButton.hidden = YES;
  492. _originalPhotoButton.hidden = YES;
  493. _originalPhotoLabel.hidden = YES;
  494. _doneButton.hidden = YES;
  495. }
  496. if (_tzImagePickerVc.photoPreviewPageDidRefreshStateBlock) {
  497. _tzImagePickerVc.photoPreviewPageDidRefreshStateBlock(_collectionView, _naviBar, _backButton, _selectButton, _indexLabel, _toolBar, _originalPhotoButton, _originalPhotoLabel, _doneButton, _numberImageView, _numberLabel);
  498. }
  499. }
  500. - (void)refreshSelectButtonImageViewContentMode {
  501. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  502. if (self->_selectButton.imageView.image.size.width <= 27) {
  503. self->_selectButton.imageView.contentMode = UIViewContentModeCenter;
  504. } else {
  505. self->_selectButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
  506. }
  507. });
  508. }
  509. - (void)showPhotoBytes {
  510. [[TZImageManager manager] getPhotosBytesWithArray:@[_models[self.currentIndex]] completion:^(NSString *totalBytes) {
  511. self->_originalPhotoLabel.text = [NSString stringWithFormat:@"(%@)",totalBytes];
  512. }];
  513. }
  514. - (NSInteger)currentIndex {
  515. return [TZCommonTools tz_isRightToLeftLayout] ? self.models.count - _currentIndex - 1 : _currentIndex;
  516. }
  517. @end