HUPhotoBrowser.m 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. //
  2. // HUPhotoBrowser.m
  3. // HUPhotoBrowser
  4. //
  5. // Created by mac on 16/2/24.
  6. // Copyright (c) 2016年 jinhuadiqigan. All rights reserved.
  7. //
  8. #import "HUPhotoBrowser.h"
  9. #import "HUPhotoBrowserCell.h"
  10. #import "hu_const.h"
  11. //#import "HUWebImage.h"
  12. #import "ZCAlertSheetView.h"
  13. #import "HUToast.h"
  14. @interface HUPhotoBrowser () <UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout> {
  15. CGRect _endTempFrame;
  16. NSInteger _currentPage;
  17. NSIndexPath *_zoomingIndexPath;
  18. BOOL _imageDidLoaded;
  19. BOOL _animationCompleted;
  20. }
  21. @property (nonatomic, strong) UIImageView *imageView;
  22. @property (nonatomic, strong) UIImageView *tmpImageView;
  23. @property (nonatomic, strong) UICollectionView *collectionView;
  24. @property (nonatomic, strong) UIView *toolBar;
  25. @property (nonatomic, weak) UILabel *countLab;
  26. @property (nonatomic, strong) NSArray *URLStrings;
  27. @property (nonatomic) NSInteger index;
  28. @property (nonatomic) NSInteger imagesCount;
  29. @property (nonatomic, copy) DismissBlock dismissDlock;
  30. @property (nonatomic, strong) NSArray *images;
  31. @property (nonatomic, strong) ZCAlertSheetView *alertView;
  32. @property (nonatomic,strong)NSMutableArray *newImages;
  33. @end
  34. @implementation HUPhotoBrowser
  35. - (NSMutableArray *)newImages{
  36. if (!_newImages) {
  37. _newImages = [NSMutableArray array];
  38. }
  39. return _newImages;
  40. }
  41. - (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
  42. {
  43. if (!error) {
  44. [ZCHUDHelper showTitle:@"保存成功"];
  45. }else{
  46. [ZCHUDHelper showTitle:@"保存失败"];
  47. }
  48. }
  49. - (void)dealloc {
  50. self.collectionView.delegate = nil;
  51. [[NSNotificationCenter defaultCenter] removeObserver:self];
  52. }
  53. + (instancetype)showFromImageView:(UIImageView *)imageView withURLStrings:(NSArray *)URLStrings placeholderURLStrings:(NSArray *)holderURLStrings atIndex:(NSInteger)index dismiss:(DismissBlock)block {
  54. HUPhotoBrowser *browser = [[HUPhotoBrowser alloc] initWithFrame:kScreenRect Type:NormalType];
  55. browser.imageView = imageView;
  56. browser.URLStrings = URLStrings;
  57. browser.imagesCount = URLStrings.count;
  58. [browser resetCountLabWithIndex:index+1];
  59. [browser configureBrowser];
  60. [browser animateImageViewAtIndex:index];
  61. browser.placeHolderUrlStrings = holderURLStrings;
  62. browser.dismissDlock = block;
  63. return browser;
  64. }
  65. + (instancetype)showFromImageView:(UIImageView *)imageView withURLStrings:(NSArray *)URLStrings placeholderImage:(UIImage *)image atIndex:(NSInteger)index dismiss:(DismissBlock)block {
  66. HUPhotoBrowser *browser = [[HUPhotoBrowser alloc] initWithFrame:kScreenRect Type:NormalType];
  67. browser.imageView = imageView;
  68. browser.URLStrings = URLStrings;
  69. browser.imagesCount = URLStrings.count;
  70. [browser resetCountLabWithIndex:index+1];
  71. [browser configureBrowser];
  72. [browser animateImageViewAtIndex:index];
  73. browser.placeholderImage = image;
  74. browser.dismissDlock = block;
  75. return browser;
  76. }
  77. + (instancetype)showFromImageView:(UIImageView *)imageView withImages:(NSArray *)images atIndex:(NSInteger)index dismiss:(DismissBlock)block{
  78. HUPhotoBrowser *browser = [[HUPhotoBrowser alloc] initWithFrame:kScreenRect Type:NormalType];
  79. browser.imageView = imageView;
  80. browser.images = images;
  81. browser.imagesCount = images.count;
  82. [browser resetCountLabWithIndex:index+1];
  83. [browser configureBrowser];
  84. [browser animateImageViewAtIndex:index];
  85. browser.dismissDlock = block;
  86. return browser;
  87. }
  88. + (nonnull instancetype)Type444showFromImageView:(nullable UIImageView *)imageView withImages:(nullable NSArray *)images atIndex:(NSInteger)index dismiss:(DismissBlock)block{
  89. HUPhotoBrowser *browser = [[HUPhotoBrowser alloc] initWithFrame:kScreenRect Type:Type44444];
  90. browser.imageView = imageView;
  91. browser.images = images;
  92. browser.imagesCount = images.count;
  93. [browser resetCountLabWithIndex:index+1];
  94. [browser configureBrowser];
  95. [browser animateImageViewAtIndex:index];
  96. browser.dismissDlock = block;
  97. return browser;
  98. }
  99. + (instancetype)showFromImageView:(UIImageView *)imageView withURLStrings:(NSArray *)URLStrings atIndex:(NSInteger)index {
  100. return [self showFromImageView:imageView withURLStrings:URLStrings placeholderImage:nil atIndex:index dismiss:nil];
  101. }
  102. + (nonnull instancetype)showFromImageView:(nullable UIImageView *)imageView withURLStrings:(nullable NSArray *)URLStrings placeholderUrlStrings:(nullable NSArray *)holderURLStrings atIndex:(NSInteger)index{
  103. return [self showFromImageView:imageView withURLStrings:URLStrings placeholderURLStrings:holderURLStrings atIndex:index dismiss:nil];
  104. }
  105. + (instancetype)showFromImageView:(UIImageView *)imageView withImages:(NSArray *)images atIndex:(NSInteger)index {
  106. return [self showFromImageView:imageView withImages:images atIndex:index dismiss:nil];
  107. }
  108. + (nonnull instancetype)Type444showFromImageView:(nullable UIImageView *)imageView withImages:(nullable NSArray *)images atIndex:(NSInteger)index{
  109. return [self Type444showFromImageView:imageView withImages:images atIndex:index dismiss:nil];
  110. }
  111. - (instancetype)initWithFrame:(CGRect)frame Type:(HUPhotoBrowserType)type{
  112. self = [super initWithFrame:frame];
  113. if (self) {
  114. self.type = type;
  115. self.backgroundColor = [UIColor blackColor];
  116. [self addSubview:self.collectionView];
  117. [self setupToolBar];
  118. [[NSNotificationCenter defaultCenter] removeObserver:self];
  119. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadForScreenRotate) name:UIDeviceOrientationDidChangeNotification object:nil];
  120. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(photoCellDidZooming:) name:kPhotoCellDidZommingNotification object:nil];
  121. }
  122. return self;
  123. }
  124. #pragma mark - UICollectionViewDataSource
  125. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  126. NSInteger count = 0;
  127. if (self.URLStrings) {
  128. count = _URLStrings.count;
  129. }
  130. else if (self.images) {
  131. count = _images.count;
  132. }
  133. return count;
  134. }
  135. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  136. HUPhotoBrowserCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kPhotoBrowserCellID forIndexPath:indexPath];
  137. cell.indexPath = indexPath;
  138. [cell resetZoomingScale];
  139. __weak __typeof(self) wself = self;
  140. cell.tapActionBlock = ^(UITapGestureRecognizer *sender) {
  141. [wself dismiss];
  142. };
  143. if (self.URLStrings) {
  144. NSURL *url = [NSURL URLWithString:self.URLStrings[indexPath.row]];
  145. if (indexPath.row != _index) {
  146. if (self.placeHolderUrlStrings) {
  147. UIImageView* temp = [[UIImageView alloc]init];
  148. [temp sd_setImageWithURL:[NSURL URLWithString:self.placeHolderUrlStrings[indexPath.row]] placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
  149. if (image) {
  150. _placeholderImage = image;
  151. [cell.imageView sd_setImageWithURL:url placeholderImage:_placeholderImage];
  152. }
  153. }];
  154. }else{
  155. [cell.imageView sd_setImageWithURL:url placeholderImage:_placeholderImage];
  156. }
  157. }
  158. else {
  159. UIImage *placeHolder = _tmpImageView.image;
  160. [cell.imageView sd_setImageWithURL:url placeholderImage:placeHolder completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
  161. if (!_imageDidLoaded) {
  162. _imageDidLoaded = YES;
  163. if (_animationCompleted) {
  164. self.collectionView.hidden = NO;
  165. [_tmpImageView removeFromSuperview];
  166. _animationCompleted = NO;
  167. }
  168. }
  169. }];
  170. }
  171. }
  172. else if (self.images) {
  173. cell.imageView.image = self.images[indexPath.row];
  174. }
  175. return cell;
  176. }
  177. - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
  178. return kScreenRect.size;
  179. }
  180. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
  181. _currentPage = scrollView.contentOffset.x/kScreenWidth + 0.5;
  182. _countLab.text = [NSString stringWithFormat:@"%zd/%zd",_currentPage+1,_imagesCount];
  183. if (_zoomingIndexPath) {
  184. [self.collectionView reloadItemsAtIndexPaths:@[_zoomingIndexPath]];
  185. _zoomingIndexPath = nil;
  186. }
  187. }
  188. #pragma mark - notification handler
  189. - (void)reloadForScreenRotate {
  190. _collectionView.frame = kScreenRect;
  191. [self.collectionView reloadData];
  192. self.collectionView.contentOffset = CGPointMake(kScreenWidth * _currentPage,0);
  193. }
  194. - (void)photoCellDidZooming:(NSNotification *)nofit {
  195. NSIndexPath *indexPath = nofit.object;
  196. _zoomingIndexPath = indexPath;
  197. }
  198. #pragma mark - getter
  199. - (UICollectionView *)collectionView {
  200. if (!_collectionView) {
  201. UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
  202. layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  203. layout.minimumInteritemSpacing = 0;
  204. layout.minimumLineSpacing = 0;
  205. _collectionView = [[UICollectionView alloc]initWithFrame:self.bounds collectionViewLayout:layout];
  206. _collectionView.hidden = YES;
  207. _collectionView.pagingEnabled = YES;
  208. _collectionView.showsHorizontalScrollIndicator = NO;
  209. }
  210. return _collectionView;
  211. }
  212. #pragma mark - private
  213. - (void)configureBrowser {
  214. self.collectionView.delegate = self;
  215. self.collectionView.dataSource = self;
  216. [self.collectionView registerClass:[HUPhotoBrowserCell class] forCellWithReuseIdentifier:kPhotoBrowserCellID];
  217. [[UIApplication sharedApplication].keyWindow addSubview:self];
  218. }
  219. - (void)setupToolBar {
  220. _toolBar = [[UIView alloc] initWithFrame:CGRectMake(0, 28, self.frame.size.width, 30)];
  221. _toolBar.backgroundColor = [UIColor clearColor];
  222. [self addSubview:_toolBar];
  223. UILabel *countLab = [[UILabel alloc] init];
  224. countLab.textColor = [UIColor whiteColor];
  225. countLab.layer.shadowOpacity = 0.9;
  226. countLab.layer.shadowColor = [UIColor blackColor].CGColor;
  227. countLab.layer.shadowOffset = CGSizeMake(1.0, 1.0);
  228. countLab.layer.shadowRadius= 2.0;
  229. countLab.font = [UIFont systemFontOfSize:15];
  230. countLab.textAlignment = NSTextAlignmentCenter;
  231. [_toolBar addSubview:countLab];
  232. _countLab = countLab;
  233. if (self.type==NormalType) {
  234. UIButton *saveBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  235. saveBtn.frame = CGRectMake(_toolBar.frame.size.width-58, 1, 50, 28);
  236. saveBtn.layer.shadowOpacity = 0.9;
  237. saveBtn.layer.shadowColor = [UIColor blackColor].CGColor;
  238. saveBtn.layer.shadowOffset = CGSizeMake(1.0, 1.0);
  239. saveBtn.layer.shadowRadius= 2.0;
  240. [saveBtn setTitle:@"保存" forState:UIControlStateNormal];
  241. [saveBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  242. saveBtn.titleLabel.font = [UIFont systemFontOfSize:15];
  243. [saveBtn addTarget:self action:@selector(saveImae) forControlEvents:UIControlEventTouchUpInside];
  244. // [JWUtils setShadow:saveBtn.layer];
  245. // [_toolBar addSubview:saveBtn];
  246. }else if(self.type==SpecialType ||self.type==Type333333){
  247. // UIButton *saveBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  248. // saveBtn.frame = CGRectMake(_toolBar.frame.size.width-58, -5, 52, 44);
  249. // saveBtn.layer.shadowOpacity = 0.9;
  250. // saveBtn.layer.shadowColor = [UIColor blackColor].CGColor;
  251. // saveBtn.layer.shadowOffset = CGSizeMake(1.0, 1.0);
  252. // saveBtn.layer.shadowRadius= 2.0;
  253. //// [saveBtn setImage:[UIImage imageNamed:@"more_icon"] forState:UIControlStateNormal];
  254. // [saveBtn setTitle:@"更多" forState:UIControlStateNormal];
  255. // saveBtn.titleLabel.font = [UIFont systemFontOfSize:14];
  256. // [saveBtn addTarget:self action:@selector(AlertShow) forControlEvents:UIControlEventTouchUpInside];
  257. //// [JWUtils setShadow:saveBtn.layer];
  258. // [_toolBar addSubview:saveBtn];
  259. UIButton *deleteBt = [UIButton buttonWithType:UIButtonTypeCustom];
  260. deleteBt.frame = CGRectMake(_toolBar.frame.size.width-80, KScreenHeight-50, 80, 50);
  261. deleteBt.layer.shadowOpacity = 0.9;
  262. deleteBt.layer.shadowColor = [UIColor blackColor].CGColor;
  263. deleteBt.layer.shadowOffset = CGSizeMake(1.0, 1.0);
  264. deleteBt.layer.shadowRadius= 2.0;
  265. [deleteBt setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  266. [deleteBt setTitle:@"删除" forState:UIControlStateNormal];
  267. [deleteBt setContentMode:UIViewContentModeScaleAspectFit];
  268. deleteBt.titleLabel.font = [UIFont systemFontOfSize:14];
  269. [deleteBt addTarget:self action:@selector(deletePhoto) forControlEvents:UIControlEventTouchUpInside];
  270. // [JWUtils setShadow:deleteBt.layer];
  271. [self addSubview:deleteBt];
  272. }else if(self.type==Type44444){
  273. }
  274. }
  275. - (void)deletePhoto{
  276. if (self.images.count==1) {
  277. if (self.delegate&&[self.delegate respondsToSelector:@selector(didDeletePhotoInIndex:)]) {
  278. [self.delegate didDeletePhotoInIndex:_currentPage];
  279. }
  280. [self dismiss];
  281. }else{
  282. self.newImages = [NSMutableArray arrayWithArray:self.images];
  283. [self.newImages removeObjectAtIndex:_currentPage];
  284. // self.imageView = self.tmpImageView;
  285. self.images = self.newImages;
  286. self.imagesCount = self.newImages.count;
  287. if (self.delegate&&[self.delegate respondsToSelector:@selector(didDeletePhotoInIndex:)]) {
  288. [self.delegate didDeletePhotoInIndex:_currentPage];
  289. }
  290. _currentPage = _index;
  291. if (_currentPage+1>self.imagesCount) {
  292. _currentPage = 0;
  293. }
  294. [self resetCountLabWithIndex:_currentPage+1];
  295. // [self animateImageViewAtIndex:_currentPage];
  296. [self.collectionView reloadData];
  297. [self.collectionView setContentOffset:CGPointMake(KScreenWidth*_currentPage, 0) animated:NO];
  298. }
  299. }
  300. - (void)animateImageViewAtIndex:(NSInteger)index {
  301. _index = index;
  302. CGRect startFrame = [self.imageView.superview convertRect:self.imageView.frame toView:[UIApplication sharedApplication].keyWindow];
  303. CGRect endFrame = kScreenRect;
  304. if (self.imageView.image) {
  305. UIImage *image = self.imageView.image;
  306. CGFloat ratio = image.size.width / image.size.height;
  307. if (ratio > kScreenRatio) {
  308. endFrame.size.width = kScreenWidth;
  309. endFrame.size.height = kScreenWidth / ratio;
  310. } else {
  311. endFrame.size.height = kScreenHeight;
  312. endFrame.size.width = kScreenHeight * ratio;
  313. }
  314. endFrame.origin.x = (kScreenWidth - endFrame.size.width) / 2;
  315. endFrame.origin.y = (kScreenHeight - endFrame.size.height) / 2;
  316. }
  317. _endTempFrame = endFrame;
  318. #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
  319. [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
  320. #endif
  321. UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:startFrame];
  322. tempImageView.image = self.imageView.image;
  323. tempImageView.contentMode = UIViewContentModeScaleAspectFit;
  324. [[UIApplication sharedApplication].keyWindow addSubview:tempImageView];
  325. _tmpImageView = tempImageView;
  326. if (self.URLStrings && !self.images) {
  327. // NSString *key = [SDWebImageDownloader cacheKeyForURL:[NSURL URLWithString:self.URLStrings[_index]]];
  328. // UIImage *image = [HUWebImageDownloader imageFromDiskCacheForKey:key];
  329. // _imageDidLoaded = image != nil;
  330. }
  331. [self.collectionView setContentOffset:CGPointMake(kScreenWidth * index,0) animated:NO];
  332. [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  333. tempImageView.frame = endFrame;
  334. } completion:^(BOOL finished) {
  335. _currentPage = index;
  336. _animationCompleted = YES;
  337. if (self.images || _imageDidLoaded || (self.URLStrings && !_imageDidLoaded)) {
  338. self.collectionView.hidden = NO;
  339. [tempImageView removeFromSuperview];
  340. _animationCompleted = NO;
  341. }
  342. }];
  343. }
  344. - (void)dismiss {
  345. #if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
  346. [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationFade];
  347. #endif
  348. if (self.dismissDlock) {
  349. HUPhotoBrowserCell *cell = (HUPhotoBrowserCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:_currentPage inSection:0]];
  350. self.dismissDlock(cell.imageView.image, _currentPage);
  351. }
  352. if (_currentPage != _index) {
  353. [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  354. self.alpha = 0;
  355. } completion:^(BOOL finished) {
  356. [self removeFromSuperview];
  357. }];
  358. return;
  359. }
  360. CGRect endFrame = [self.imageView.superview convertRect:self.imageView.frame toView:[UIApplication sharedApplication].keyWindow];
  361. UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:_endTempFrame];
  362. tempImageView.image = self.imageView.image;
  363. tempImageView.contentMode = UIViewContentModeScaleAspectFit;
  364. self.collectionView.hidden = YES;
  365. [[UIApplication sharedApplication].keyWindow addSubview:tempImageView];
  366. [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
  367. tempImageView.frame = endFrame;
  368. self.alpha = 0;
  369. } completion:^(BOOL finished) {
  370. [self removeFromSuperview];
  371. [tempImageView removeFromSuperview];
  372. }];
  373. }
  374. - (void)resetCountLabWithIndex:(NSInteger)index {
  375. NSString *text = [NSString stringWithFormat:@"%zd%zd",_imagesCount,_imagesCount];
  376. CGFloat width = [text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]}].width+8;
  377. _countLab.frame = CGRectMake(8, 1, MAX(50, width), 28);
  378. _countLab.text = [NSString stringWithFormat:@"%zd/%zd",index,_imagesCount];
  379. }
  380. - (void)saveImae {
  381. HUPhotoBrowserCell *cell = (HUPhotoBrowserCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:_currentPage inSection:0]];
  382. UIImage *seavedImage = cell.imageView.image;
  383. UIImageWriteToSavedPhotosAlbum(seavedImage, self, @selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:), nil);
  384. }
  385. - (void)setType:(HUPhotoBrowserType)type{
  386. _type = type;
  387. // if (type == Type333333 || type==Type44444) {
  388. // [_toolBar setHidden:NO];
  389. // }
  390. }
  391. @end