MJPhotoBrowser.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. //
  2. // MJPhotoBrowser.m
  3. //
  4. // Created by mj on 13-3-4.
  5. // Copyright (c) 2013年 itcast. All rights reserved.
  6. #import <QuartzCore/QuartzCore.h>
  7. #import "MJPhotoBrowser.h"
  8. #import "MJPhoto.h"
  9. //#import "SDWebImageManager+MJ.h"
  10. #import "SDWebImageManager.h"
  11. //#import <SDWebImage/SDWebImageManager.h>
  12. #import "MJPhotoView.h"
  13. #import "MJPhotoToolbar.h"
  14. #import "JChatConstants.h"
  15. //#define kPadding 10
  16. #define kPadding 0
  17. #define kPhotoViewTagOffset 1000
  18. #define kPhotoViewIndex(photoView) ([photoView tag] - kPhotoViewTagOffset)
  19. @interface MJPhotoBrowser () <MJPhotoViewDelegate, MJPhotoToolbarDelegate>
  20. {
  21. // 滚动的view
  22. UIScrollView *_photoScrollView;
  23. // 所有的图片view
  24. NSMutableSet *_visiblePhotoViews;
  25. NSMutableSet *_reusablePhotoViews;
  26. // 工具条
  27. MJPhotoToolbar * _toolbar;
  28. NSProgress *_progress;
  29. // 一开始的状态栏
  30. BOOL _statusBarHiddenInited;
  31. }
  32. @end
  33. @implementation MJPhotoBrowser
  34. #pragma mark - Lifecycle
  35. - (void)loadView
  36. {
  37. // _statusBarHiddenInited = [UIApplication sharedApplication].isStatusBarHidden;
  38. // 隐藏状态栏
  39. // [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
  40. self.view = [[UIView alloc] init];
  41. self.view.frame = [UIScreen mainScreen].bounds;
  42. self.view.backgroundColor = [UIColor blackColor];
  43. }
  44. - (void)viewDidLoad
  45. {
  46. [super viewDidLoad];
  47. // 1.创建UIScrollView
  48. [self createScrollView];
  49. // 2.创建工具条
  50. [self createToolbar];
  51. }
  52. - (void)show
  53. {
  54. UIWindow *window = [UIApplication sharedApplication].keyWindow;
  55. [window addSubview:self.view];
  56. [window.rootViewController addChildViewController:self];
  57. if (_currentPhotoIndex == 0) {
  58. [self showPhotos];
  59. }
  60. }
  61. #pragma mark - 私有方法
  62. #pragma mark 创建工具条
  63. - (void)createToolbar
  64. {
  65. CGFloat barHeight = 44;
  66. CGFloat barY = self.view.frame.size.height - barHeight;
  67. _toolbar = [[MJPhotoToolbar alloc] init];
  68. _toolbar.Delegate = self;
  69. _toolbar.frame = CGRectMake(0, barY, self.view.frame.size.width, barHeight);
  70. _toolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
  71. _toolbar.photos = _photos;
  72. [self.view addSubview:_toolbar];
  73. [self updateTollbarState];
  74. }
  75. - (void)downLoadThisImage:(NSInteger)ThisImageIndex {
  76. // MJPhoto *photo = [_photos objectAtIndex:ThisImageIndex];
  77. // JPIMMessageModel *messageModel = [_conversation getMessage:photo.messageId];
  78. // if (![[self jsonStringToDictionary:messageModel.content] objectForKey:kimgresource]) {
  79. // _progress= [NSProgress progressWithTotalUnitCount:100];
  80. // [_progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil];
  81. // [JMSGMessageManager getMetaImageFromMessage:messageModel withConversation:_conversation withProgress:_progress succeedBlock:^(NSData *image) {
  82. // JPIMMessageModel * model = [_conversation getMessage:photo.messageId];
  83. // NSLog(@"download img successs %@,",model.content);
  84. // [_photos removeObjectAtIndex:_currentPhotoIndex];
  85. // [_photos insertObject:[[self jsonStringToDictionary:messageModel.content] objectForKey:kimgresource] atIndex:_currentPhotoIndex];
  86. // [self setCurrentPhotoIndex:_currentPhotoIndex];
  87. // } failBlock:^(NSError *error) {
  88. // NSLog(@"download img error");
  89. // }];
  90. // }
  91. }
  92. #pragma mark --jsonStringTo字典
  93. - (NSDictionary *)jsonStringToDictionary:(NSString *)jsonString {
  94. NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
  95. NSDictionary *content = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
  96. return content;
  97. }
  98. - (void)observeValueForKeyPath:(NSString *)keyPath
  99. ofObject:(id)object
  100. change:(NSDictionary *)change
  101. context:(void *)context {
  102. DDLogDebug(@"_progress= %f", _progress.fractionCompleted);
  103. }
  104. - (void)DeleteThisImage:(NSInteger)ThisImageIndex {
  105. NSLog(@"ThisImageIndex---%ld", (long)ThisImageIndex );
  106. NSLog(@"_currentPhotoIndex---%lu", (unsigned long)_currentPhotoIndex );
  107. if ( ThisImageIndex == 0 ) {
  108. _currentPhotoIndex = 1;
  109. } else if ( ThisImageIndex == _currentPhotoIndex ) {
  110. _currentPhotoIndex = _currentPhotoIndex - 1;
  111. } else{
  112. _currentPhotoIndex = _currentPhotoIndex - 1;
  113. }
  114. [_photos removeObjectAtIndex: ThisImageIndex];
  115. [self setCurrentPhotoIndex: _currentPhotoIndex ];
  116. }
  117. #pragma mark 创建UIScrollView
  118. - (void)createScrollView
  119. {
  120. CGRect frame = self.view.bounds;
  121. frame.origin.x -= kPadding;
  122. frame.size.width += (2 * kPadding);
  123. _photoScrollView = [[UIScrollView alloc] initWithFrame:frame];
  124. _photoScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  125. _photoScrollView.pagingEnabled = YES;
  126. _photoScrollView.delegate = self;
  127. _photoScrollView.showsHorizontalScrollIndicator = NO;
  128. _photoScrollView.showsVerticalScrollIndicator = NO;
  129. _photoScrollView.backgroundColor = [UIColor clearColor];
  130. _photoScrollView.contentSize = CGSizeMake(frame.size.width * _photos.count, 0);
  131. [self.view addSubview:_photoScrollView];
  132. _photoScrollView.contentOffset = CGPointMake(_currentPhotoIndex * frame.size.width, 0);
  133. _photoScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
  134. }
  135. - (void)setPhotos:(NSMutableArray *)photos {
  136. _photos = photos;
  137. if (photos.count > 1) {
  138. _visiblePhotoViews = [NSMutableSet set];
  139. _reusablePhotoViews = [NSMutableSet set];
  140. }
  141. for (int i = 0; i<_photos.count; i++) {
  142. MJPhoto *photo = _photos[i];
  143. photo.index = i;
  144. photo.firstShow = i == _currentPhotoIndex;
  145. }
  146. }
  147. #pragma mark 设置选中的图片
  148. - (void)setCurrentPhotoIndex:(NSUInteger)currentPhotoIndex
  149. {
  150. _currentPhotoIndex = currentPhotoIndex;
  151. for (int i = 0; i<_photos.count; i++) {
  152. MJPhoto *photo = _photos[i];
  153. photo.firstShow = i == currentPhotoIndex;
  154. }
  155. if ([self isViewLoaded]) {
  156. _photoScrollView.contentOffset = CGPointMake(_currentPhotoIndex * _photoScrollView.frame.size.width, 0);
  157. // 显示所有的相片
  158. [self showPhotos];
  159. }
  160. }
  161. //撤回消息移除 browser
  162. -(void)retractMsgDismissBrowser; {
  163. [_toolbar removeFromSuperview];
  164. [self.view removeFromSuperview];
  165. [self removeFromParentViewController];
  166. }
  167. #pragma mark - MJPhotoView代理
  168. - (void)photoViewSingleTap:(MJPhotoView *)photoView
  169. {
  170. // [UIApplication sharedApplication].statusBarHidden = _statusBarHiddenInited;
  171. self.view.backgroundColor = [UIColor clearColor];
  172. // 移除工具条
  173. [_toolbar removeFromSuperview];
  174. if ( [_delegate respondsToSelector:@selector(CellPhotoImageReload)] ) {
  175. [_delegate CellPhotoImageReload];
  176. }
  177. }
  178. - (void)photoViewDidEndZoom:(MJPhotoView *)photoView
  179. {
  180. [self.view removeFromSuperview];
  181. [self removeFromParentViewController];
  182. }
  183. - (void)photoViewImageFinishLoad:(MJPhotoView *)photoView
  184. {
  185. _toolbar.currentPhotoIndex = _currentPhotoIndex;
  186. MJPhoto *photo = [_photos objectAtIndex:_currentPhotoIndex];
  187. photo.url = photoView.photo.url;
  188. MJPhoto *toolbarPhoto = [_toolbar.photos objectAtIndex:_currentPhotoIndex];
  189. toolbarPhoto.url = photoView.photo.url;
  190. }
  191. #pragma mark 显示照片
  192. - (void)showPhotos
  193. {
  194. // 只有一张图片
  195. if (_photos.count == 1) {
  196. [self showPhotoViewAtIndex:0];
  197. return;
  198. }
  199. CGRect visibleBounds = _photoScrollView.bounds;
  200. int firstIndex = (int)floorf((CGRectGetMinX(visibleBounds)+kPadding*2) / CGRectGetWidth(visibleBounds));
  201. int lastIndex = (int)floorf((CGRectGetMaxX(visibleBounds)-kPadding*2-1) / CGRectGetWidth(visibleBounds));
  202. if (firstIndex < 0) firstIndex = 0;
  203. if (firstIndex >= _photos.count) firstIndex = (int)_photos.count - 1;
  204. if (lastIndex < 0) lastIndex = 0;
  205. if (lastIndex >= _photos.count) lastIndex = (int)_photos.count - 1;
  206. // 回收不再显示的ImageView
  207. NSInteger photoViewIndex;
  208. for (MJPhotoView *photoView in _visiblePhotoViews) {
  209. photoViewIndex = kPhotoViewIndex(photoView);
  210. if (photoViewIndex < firstIndex || photoViewIndex > lastIndex) {
  211. [_reusablePhotoViews addObject:photoView];
  212. photoView.photo.image = nil;
  213. [photoView removeFromSuperview];
  214. }
  215. }
  216. [_visiblePhotoViews minusSet:_reusablePhotoViews];
  217. while (_reusablePhotoViews.count > 2) {
  218. [_reusablePhotoViews removeObject:[_reusablePhotoViews anyObject]];
  219. }
  220. for (NSUInteger index = firstIndex; index <= lastIndex; index++) {
  221. if (![self isShowingPhotoViewAtIndex:index]) {
  222. [self showPhotoViewAtIndex:(int)index];
  223. }
  224. }
  225. }
  226. #pragma mark 显示一个图片view
  227. - (void)showPhotoViewAtIndex:(int)index
  228. {
  229. if (index < 0 || [_photos count] < index + 1) {
  230. return;
  231. }
  232. MJPhotoView *photoView = [self dequeueReusablePhotoView];
  233. if (!photoView) { // 添加新的图片view
  234. photoView = [[MJPhotoView alloc] init];
  235. photoView.photoViewDelegate = self;
  236. }
  237. // 调整当期页的frame
  238. CGRect bounds = _photoScrollView.bounds;
  239. CGRect photoViewFrame = bounds;
  240. photoViewFrame.size.width -= (2 * kPadding);
  241. photoViewFrame.origin.x = (bounds.size.width * index) + kPadding;
  242. photoView.tag = kPhotoViewTagOffset + index;
  243. MJPhoto *photo = _photos[index];
  244. photoView.frame = photoViewFrame;
  245. photoView.photo = photo;
  246. photoView.conversation = _conversation;
  247. [_visiblePhotoViews addObject:photoView];
  248. [_photoScrollView addSubview:photoView];
  249. [self loadImageNearIndex:index];
  250. }
  251. #pragma mark 加载index附近的图片
  252. - (void)loadImageNearIndex:(int)index
  253. {
  254. if (index > 0) {
  255. MJPhoto *photo = _photos[index - 1];
  256. // [SDWebImageManager downloadWithURL:photo.url];
  257. [[SDWebImageManager sharedManager] loadImageWithURL:photo.url options:1 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
  258. }];
  259. // [[SDWebImageManager sharedManager] downloadImageWithURL:photo.url options:1 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
  260. //
  261. // }];
  262. }
  263. if (index < _photos.count - 1) {
  264. MJPhoto *photo = _photos[index + 1];
  265. // [SDWebImageManager downloadWithURL:photo.url];
  266. [[SDWebImageManager sharedManager]loadImageWithURL:photo.url options:1 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
  267. }];
  268. // [[SDWebImageManager sharedManager] downloadImageWithURL:photo.url options:1 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
  269. //
  270. // }];
  271. }
  272. }
  273. #pragma mark index这页是否正在显示
  274. - (BOOL)isShowingPhotoViewAtIndex:(NSUInteger)index {
  275. for (MJPhotoView *photoView in _visiblePhotoViews) {
  276. if (kPhotoViewIndex(photoView) == index) {
  277. return YES;
  278. }
  279. }
  280. return NO;
  281. }
  282. #pragma mark 循环利用某个view
  283. - (MJPhotoView *)dequeueReusablePhotoView
  284. {
  285. MJPhotoView *photoView = [_reusablePhotoViews anyObject];
  286. if (photoView) {
  287. [_reusablePhotoViews removeObject:photoView];
  288. }
  289. return photoView;
  290. }
  291. #pragma mark 更新toolbar状态
  292. - (void)updateTollbarState
  293. {
  294. _currentPhotoIndex = _photoScrollView.contentOffset.x / _photoScrollView.frame.size.width;
  295. _toolbar.currentPhotoIndex = _currentPhotoIndex;
  296. }
  297. #pragma mark - UIScrollView Delegate
  298. - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  299. [self showPhotos];
  300. [self updateTollbarState];
  301. }
  302. @end