口袋优选

SDPhotoBrowser.m 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. //
  2. // SDPhotoBrowser.m
  3. // photobrowser
  4. //
  5. // Created by aier on 15-2-3.
  6. // Copyright (c) 2015年 aier. All rights reserved.
  7. //
  8. #import "SDPhotoBrowser.h"
  9. #import "UIImageView+WebCache.h"
  10. #import "SDBrowserImageView.h"
  11. // ============在这里方便配置样式相关设置===========
  12. // ||
  13. // ||
  14. // ||
  15. // \\//
  16. // \/
  17. #import "SDPhotoBrowserConfig.h"
  18. // =============================================
  19. @implementation SDPhotoBrowser
  20. {
  21. UIScrollView *_scrollView;
  22. BOOL _hasShowedFistView;
  23. UILabel *_indexLabel;
  24. UIButton *_saveButton;
  25. UIActivityIndicatorView *_indicatorView;
  26. BOOL _willDisappear;
  27. }
  28. - (id)initWithFrame:(CGRect)frame
  29. {
  30. self = [super initWithFrame:frame];
  31. if (self) {
  32. self.backgroundColor = SDPhotoBrowserBackgrounColor;
  33. }
  34. return self;
  35. }
  36. - (void)didMoveToSuperview
  37. {
  38. [self setupScrollView];
  39. [self setupToolbars];
  40. }
  41. - (void)dealloc
  42. {
  43. [[UIApplication sharedApplication].keyWindow removeObserver:self forKeyPath:@"frame"];
  44. }
  45. - (void)setupToolbars
  46. {
  47. // 1. 序标
  48. UILabel *indexLabel = [[UILabel alloc] init];
  49. indexLabel.bounds = CGRectMake(0, 0, 80, 30);
  50. indexLabel.textAlignment = NSTextAlignmentCenter;
  51. indexLabel.textColor = [UIColor whiteColor];
  52. indexLabel.font = [UIFont boldSystemFontOfSize:20];
  53. indexLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
  54. indexLabel.layer.cornerRadius = indexLabel.bounds.size.height * 0.5;
  55. indexLabel.clipsToBounds = YES;
  56. if (self.imageCount > 1) {
  57. indexLabel.text = [NSString stringWithFormat:@"1/%ld", (long)self.imageCount];
  58. }
  59. _indexLabel = indexLabel;
  60. [self addSubview:indexLabel];
  61. // 2.保存按钮
  62. UIButton *saveButton = [[UIButton alloc] init];
  63. [saveButton setTitle:@"保存" forState:UIControlStateNormal];
  64. [saveButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  65. saveButton.backgroundColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:0.90f];
  66. saveButton.layer.cornerRadius = 5;
  67. saveButton.clipsToBounds = YES;
  68. [saveButton addTarget:self action:@selector(saveImage) forControlEvents:UIControlEventTouchUpInside];
  69. _saveButton = saveButton;
  70. [self addSubview:saveButton];
  71. }
  72. - (void)saveImage
  73. {
  74. int index = _scrollView.contentOffset.x / _scrollView.bounds.size.width;
  75. UIImageView *currentImageView = _scrollView.subviews[index];
  76. UIImageWriteToSavedPhotosAlbum(currentImageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
  77. UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] init];
  78. indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
  79. indicator.center = self.center;
  80. _indicatorView = indicator;
  81. [[UIApplication sharedApplication].keyWindow addSubview:indicator];
  82. [indicator startAnimating];
  83. }
  84. - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
  85. {
  86. [_indicatorView removeFromSuperview];
  87. UILabel *label = [[UILabel alloc] init];
  88. label.textColor = [UIColor whiteColor];
  89. label.backgroundColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:0.90f];
  90. label.layer.cornerRadius = 5;
  91. label.clipsToBounds = YES;
  92. label.bounds = CGRectMake(0, 0, 150, 30);
  93. label.center = self.center;
  94. label.textAlignment = NSTextAlignmentCenter;
  95. label.font = [UIFont boldSystemFontOfSize:17];
  96. [[UIApplication sharedApplication].keyWindow addSubview:label];
  97. [[UIApplication sharedApplication].keyWindow bringSubviewToFront:label];
  98. if (error) {
  99. label.text = SDPhotoBrowserSaveImageFailText;
  100. } else {
  101. label.text = SDPhotoBrowserSaveImageSuccessText;
  102. }
  103. [label performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1.0];
  104. }
  105. - (void)setupScrollView
  106. {
  107. _scrollView = [[UIScrollView alloc] init];
  108. _scrollView.delegate = self;
  109. _scrollView.showsHorizontalScrollIndicator = NO;
  110. _scrollView.showsVerticalScrollIndicator = NO;
  111. _scrollView.pagingEnabled = YES;
  112. [self addSubview:_scrollView];
  113. for (int i = 0; i < self.imageCount; i++) {
  114. SDBrowserImageView *imageView = [[SDBrowserImageView alloc] init];
  115. imageView.tag = i;
  116. // 单击图片
  117. UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(photoClick:)];
  118. // 双击放大图片
  119. UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDoubleTaped:)];
  120. doubleTap.numberOfTapsRequired = 2;
  121. [self addGestureRecognizer:doubleTap];
  122. [singleTap requireGestureRecognizerToFail:doubleTap];
  123. [imageView addGestureRecognizer:singleTap];
  124. [imageView addGestureRecognizer:doubleTap];
  125. [_scrollView addSubview:imageView];
  126. }
  127. [self setupImageOfImageViewForIndex:self.currentImageIndex];
  128. }
  129. // 加载图片
  130. - (void)setupImageOfImageViewForIndex:(NSInteger)index
  131. {
  132. SDBrowserImageView *imageView = _scrollView.subviews[index];
  133. self.currentImageIndex = index;
  134. if (imageView.hasLoadedImage) return;
  135. if ([self highQualityImageURLForIndex:index]) {
  136. [imageView setImageWithURL:[self highQualityImageURLForIndex:index] placeholderImage:[self placeholderImageForIndex:index]];
  137. } else {
  138. imageView.image = [self placeholderImageForIndex:index];
  139. }
  140. imageView.hasLoadedImage = YES;
  141. }
  142. - (void)photoClick:(UITapGestureRecognizer *)recognizer
  143. {
  144. _scrollView.hidden = YES;
  145. _willDisappear = YES;
  146. SDBrowserImageView *currentImageView = (SDBrowserImageView *)recognizer.view;
  147. NSInteger currentIndex = currentImageView.tag;
  148. UIView *sourceView = self.sourceImagesContainerView.subviews[currentIndex];
  149. CGRect targetTemp = [self.sourceImagesContainerView convertRect:sourceView.frame toView:self];
  150. UIImageView *tempView = [[UIImageView alloc] init];
  151. tempView.contentMode = sourceView.contentMode;
  152. tempView.clipsToBounds = YES;
  153. tempView.image = currentImageView.image;
  154. CGFloat h = (self.bounds.size.width / currentImageView.image.size.width) * currentImageView.image.size.height;
  155. if (!currentImageView.image) { // 防止 因imageview的image加载失败 导致 崩溃
  156. h = self.bounds.size.height;
  157. }
  158. tempView.bounds = CGRectMake(0, 0, self.bounds.size.width, h);
  159. tempView.center = self.center;
  160. [self addSubview:tempView];
  161. _saveButton.hidden = YES;
  162. [UIView animateWithDuration:SDPhotoBrowserHideImageAnimationDuration animations:^{
  163. tempView.frame = targetTemp;
  164. self.backgroundColor = [UIColor clearColor];
  165. _indexLabel.alpha = 0.1;
  166. } completion:^(BOOL finished) {
  167. [self removeFromSuperview];
  168. }];
  169. }
  170. - (void)imageViewDoubleTaped:(UITapGestureRecognizer *)recognizer
  171. {
  172. SDBrowserImageView *imageView = (SDBrowserImageView *)recognizer.view;
  173. CGFloat scale;
  174. if (imageView.isScaled) {
  175. scale = 1.0;
  176. } else {
  177. scale = 2.0;
  178. }
  179. SDBrowserImageView *view = (SDBrowserImageView *)recognizer.view;
  180. [view doubleTapToZommWithScale:scale];
  181. }
  182. - (void)layoutSubviews
  183. {
  184. [super layoutSubviews];
  185. CGRect rect = self.bounds;
  186. rect.size.width += SDPhotoBrowserImageViewMargin * 2;
  187. _scrollView.bounds = rect;
  188. _scrollView.center = self.center;
  189. CGFloat y = 0;
  190. CGFloat w = _scrollView.frame.size.width - SDPhotoBrowserImageViewMargin * 2;
  191. CGFloat h = _scrollView.frame.size.height;
  192. [_scrollView.subviews enumerateObjectsUsingBlock:^(SDBrowserImageView *obj, NSUInteger idx, BOOL *stop) {
  193. CGFloat x = SDPhotoBrowserImageViewMargin + idx * (SDPhotoBrowserImageViewMargin * 2 + w);
  194. obj.frame = CGRectMake(x, y, w, h);
  195. }];
  196. _scrollView.contentSize = CGSizeMake(_scrollView.subviews.count * _scrollView.frame.size.width, 0);
  197. _scrollView.contentOffset = CGPointMake(self.currentImageIndex * _scrollView.frame.size.width, 0);
  198. if (!_hasShowedFistView) {
  199. [self showFirstImage];
  200. }
  201. _indexLabel.center = CGPointMake(self.bounds.size.width * 0.5, 35);
  202. _saveButton.frame = CGRectMake(30, self.bounds.size.height - 70, 50, 25);
  203. }
  204. - (void)show
  205. {
  206. UIWindow *window = [UIApplication sharedApplication].keyWindow;
  207. self.frame = window.bounds;
  208. [window addObserver:self forKeyPath:@"frame" options:0 context:nil];
  209. [window addSubview:self];
  210. }
  211. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView *)object change:(NSDictionary *)change context:(void *)context
  212. {
  213. if ([keyPath isEqualToString:@"frame"]) {
  214. self.frame = object.bounds;
  215. SDBrowserImageView *currentImageView = _scrollView.subviews[_currentImageIndex];
  216. if ([currentImageView isKindOfClass:[SDBrowserImageView class]]) {
  217. [currentImageView clear];
  218. }
  219. }
  220. }
  221. - (void)showFirstImage
  222. {
  223. UIView *sourceView = self.sourceImagesContainerView.subviews[self.currentImageIndex];
  224. CGRect rect = [self.sourceImagesContainerView convertRect:sourceView.frame toView:self];
  225. UIImageView *tempView = [[UIImageView alloc] init];
  226. tempView.image = [self placeholderImageForIndex:self.currentImageIndex];
  227. [self addSubview:tempView];
  228. CGRect targetTemp = [_scrollView.subviews[self.currentImageIndex] bounds];
  229. tempView.frame = rect;
  230. tempView.contentMode = [_scrollView.subviews[self.currentImageIndex] contentMode];
  231. _scrollView.hidden = YES;
  232. [UIView animateWithDuration:SDPhotoBrowserShowImageAnimationDuration animations:^{
  233. tempView.center = self.center;
  234. tempView.bounds = (CGRect){CGPointZero, targetTemp.size};
  235. } completion:^(BOOL finished) {
  236. _hasShowedFistView = YES;
  237. [tempView removeFromSuperview];
  238. _scrollView.hidden = NO;
  239. }];
  240. }
  241. - (UIImage *)placeholderImageForIndex:(NSInteger)index
  242. {
  243. if ([self.delegate respondsToSelector:@selector(photoBrowser:placeholderImageForIndex:)]) {
  244. return [self.delegate photoBrowser:self placeholderImageForIndex:index];
  245. }
  246. return nil;
  247. }
  248. - (NSURL *)highQualityImageURLForIndex:(NSInteger)index
  249. {
  250. if ([self.delegate respondsToSelector:@selector(photoBrowser:highQualityImageURLForIndex:)]) {
  251. return [self.delegate photoBrowser:self highQualityImageURLForIndex:index];
  252. }
  253. return nil;
  254. }
  255. #pragma mark - scrollview代理方法
  256. - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  257. {
  258. int index = (scrollView.contentOffset.x + _scrollView.bounds.size.width * 0.5) / _scrollView.bounds.size.width;
  259. // 有过缩放的图片在拖动一定距离后清除缩放
  260. CGFloat margin = 150;
  261. CGFloat x = scrollView.contentOffset.x;
  262. if ((x - index * self.bounds.size.width) > margin || (x - index * self.bounds.size.width) < - margin) {
  263. SDBrowserImageView *imageView = _scrollView.subviews[index];
  264. if (imageView.isScaled) {
  265. [UIView animateWithDuration:0.5 animations:^{
  266. imageView.transform = CGAffineTransformIdentity;
  267. } completion:^(BOOL finished) {
  268. [imageView eliminateScale];
  269. }];
  270. }
  271. }
  272. if (!_willDisappear) {
  273. _indexLabel.text = [NSString stringWithFormat:@"%d/%ld", index + 1, (long)self.imageCount];
  274. }
  275. [self setupImageOfImageViewForIndex:index];
  276. }
  277. @end
  278. // 版权属于原作者
  279. // http://code4app.com (cn) http://code4app.net (en)
  280. // 发布代码于最专业的源码分享网站: Code4App.com