// // MJPhotoBrowser.m // // Created by mj on 13-3-4. // Copyright (c) 2013年 itcast. All rights reserved. #import #import "MJPhotoBrowser.h" #import "MJPhoto.h" #import "MJPhotoView.h" #import "MJPhotoToolbar.h" #import #define kPadding 10 #define kPhotoViewTagOffset 1000 #define kPhotoViewIndex(photoView) ([photoView tag] - kPhotoViewTagOffset) @interface MJPhotoBrowser () { // 滚动的view UIScrollView *_photoScrollView; // 所有的图片view NSMutableSet *_visiblePhotoViews; NSMutableSet *_reusablePhotoViews; // 工具条 MJPhotoToolbar *_toolbar; // 一开始的状态栏 BOOL _statusBarHiddenInited; } @end @implementation MJPhotoBrowser #pragma mark - Lifecycle - (void)loadView { _statusBarHiddenInited = [UIApplication sharedApplication].isStatusBarHidden; // 隐藏状态栏 [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade]; self.view = [[UIView alloc] init]; self.view.frame = [UIScreen mainScreen].bounds; self.view.backgroundColor = [UIColor blackColor]; } - (void)viewDidLoad { [super viewDidLoad]; // 1.创建UIScrollView [self createScrollView]; // 2.创建工具条 [self createToolbar]; } - (void)show { if (_photos.count == 0) { return; } UIWindow *window = [UIApplication sharedApplication].keyWindow; [window addSubview:self.view]; [window.rootViewController addChildViewController:self]; if (_currentPhotoIndex == 0) { [self showPhotos]; } } #pragma mark - 私有方法 #pragma mark 创建工具条 - (void)createToolbar { CGFloat barHeight = 44; CGFloat barY = self.view.frame.size.height - barHeight - kNavOffSet; _toolbar = [[MJPhotoToolbar alloc] init]; _toolbar.frame = CGRectMake(0, barY, self.view.frame.size.width, barHeight); _toolbar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin; _toolbar.photos = _photos; [self.view addSubview:_toolbar]; [self updateTollbarState]; } #pragma mark 创建UIScrollView - (void)createScrollView { CGRect frame = self.view.bounds; frame.origin.x -= kPadding; frame.size.width += (2 * kPadding); _photoScrollView = [[UIScrollView alloc] initWithFrame:frame]; _photoScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _photoScrollView.pagingEnabled = YES; _photoScrollView.delegate = self; _photoScrollView.showsHorizontalScrollIndicator = NO; _photoScrollView.showsVerticalScrollIndicator = NO; _photoScrollView.backgroundColor = [UIColor clearColor]; _photoScrollView.contentSize = CGSizeMake(frame.size.width * _photos.count, 0); [self.view addSubview:_photoScrollView]; //danson //创建完scroll 先设置一个偏移量 调用scroll滑动方法 目的是保存按钮第一次有效 //_photoScrollView.contentOffset = CGPointMake(5, 0); //上面的做法会使起始图片的现实产生问题 改成下面这种做法 估计会更好 _photoScrollView.contentOffset = CGPointMake(_currentPhotoIndex * frame.size.width + 1, 0); } - (void)setPhotos:(NSArray *)photos { _photos = photos; if (photos.count > 1) { _visiblePhotoViews = [NSMutableSet set]; _reusablePhotoViews = [NSMutableSet set]; } for (int i = 0; i<_photos.count; i++) { MJPhoto *photo = _photos[i]; photo.index = i; photo.firstShow = i == _currentPhotoIndex; } } #pragma mark 设置选中的图片 - (void)setCurrentPhotoIndex:(NSUInteger)currentPhotoIndex { _currentPhotoIndex = currentPhotoIndex; //这样不是更方便 好吧 这样会有很多firstShow // MJPhoto *photo = _photos[currentPhotoIndex]; // photo.firstShow = YES; for (int i = 0; i<_photos.count; i++) { MJPhoto *photo = _photos[i]; photo.firstShow = i == currentPhotoIndex ? YES : NO; } if ([self isViewLoaded]) { _photoScrollView.contentOffset = CGPointMake(_currentPhotoIndex * _photoScrollView.frame.size.width, 0); // 显示所有的相片 [self showPhotos]; } } #pragma mark - MJPhotoView代理 - (void)photoViewSingleTap:(MJPhotoView *)photoView { [UIApplication sharedApplication].statusBarHidden = _statusBarHiddenInited; // 移除工具条 [_toolbar removeFromSuperview]; } - (void)photoViewDidEndZoom:(MJPhotoView *)photoView { self.view.backgroundColor = [UIColor clearColor]; [self.view removeFromSuperview]; [self removeFromParentViewController]; } - (void)photoViewImageFinishLoad:(MJPhotoView *)photoView { _toolbar.currentPhotoIndex = _currentPhotoIndex; } #pragma mark 显示照片 - (void)showPhotos { // if ([self isViewLoaded]) { // _photoScrollView.contentOffset = CGPointMake(_currentPhotoIndex * _photoScrollView.frame.size.width, 0); // } // 只有一张图片 if (_photos.count == 1) { //danson //scroll代理方法调了3次 为了不添加重复的scroll 做个判断 //NSLog(@"%d",(int)_photoScrollView.subviews.count); if (_photoScrollView.subviews.count == 0) { [self showPhotoViewAtIndex:0]; } return; } CGRect visibleBounds = _photoScrollView.bounds; int firstIndex = (int)floorf((CGRectGetMinX(visibleBounds)+kPadding*2) / CGRectGetWidth(visibleBounds)); int lastIndex = (int)floorf((CGRectGetMaxX(visibleBounds)-kPadding*2-1) / CGRectGetWidth(visibleBounds)); if (firstIndex < 0) firstIndex = 0; if (firstIndex >= _photos.count) firstIndex = (int)_photos.count - 1; if (lastIndex < 0) lastIndex = 0; if (lastIndex >= _photos.count) lastIndex = (int)_photos.count - 1; // 回收不再显示的ImageView NSInteger photoViewIndex; for (MJPhotoView *photoView in _visiblePhotoViews) { photoViewIndex = kPhotoViewIndex(photoView); if (photoViewIndex < firstIndex || photoViewIndex > lastIndex) { [_reusablePhotoViews addObject:photoView]; [photoView removeFromSuperview]; } } [_visiblePhotoViews minusSet:_reusablePhotoViews]; while (_reusablePhotoViews.count > 2) { [_reusablePhotoViews removeObject:[_reusablePhotoViews anyObject]]; } for (NSUInteger index = firstIndex; index <= lastIndex; index++) { if (![self isShowingPhotoViewAtIndex:index]) { [self showPhotoViewAtIndex:(int)index]; } } } #pragma mark 显示一个图片view - (void)showPhotoViewAtIndex:(int)index { //先移除 MJPhotoView *photoView = [self dequeueReusablePhotoView]; if (!photoView) { // 添加新的图片view photoView = [[MJPhotoView alloc] init]; photoView.photoViewDelegate = self; } // 调整当前页的frame CGRect bounds = _photoScrollView.bounds; CGRect photoViewFrame = bounds; photoViewFrame.size.width -= (2 * kPadding); photoViewFrame.origin.x = (bounds.size.width * index) + kPadding; photoView.tag = kPhotoViewTagOffset + index; MJPhoto *photo = _photos[index]; photoView.frame = photoViewFrame; photoView.photo = photo; [_visiblePhotoViews addObject:photoView]; [_photoScrollView addSubview:photoView]; [self loadImageNearIndex:index]; } #pragma mark 加载index附近的图片 - (void)loadImageNearIndex:(int)index { if (index > 0) { MJPhoto *photo = _photos[index - 1]; [[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:@[photo.url]]; } if (index < _photos.count - 1) { MJPhoto *photo = _photos[index + 1]; [[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:@[photo.url]]; } } #pragma mark index这页是否正在显示 - (BOOL)isShowingPhotoViewAtIndex:(NSUInteger)index { for (MJPhotoView *photoView in _visiblePhotoViews) { if (kPhotoViewIndex(photoView) == index) { return YES; } } return NO; } #pragma mark 循环利用某个view - (MJPhotoView *)dequeueReusablePhotoView { MJPhotoView *photoView = [_reusablePhotoViews anyObject]; if (photoView) { [_reusablePhotoViews removeObject:photoView]; } return photoView; } #pragma mark 更新toolbar状态 - (void)updateTollbarState { _currentPhotoIndex = _photoScrollView.contentOffset.x / _photoScrollView.frame.size.width; _toolbar.currentPhotoIndex = _currentPhotoIndex; } #pragma mark - UIScrollView Delegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { //NSLog(@"scroll代理"); [self showPhotos]; [self updateTollbarState]; } @end