123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- //
- // MJPhotoBrowser.m
- //
- // Created by mj on 13-3-4.
- // Copyright (c) 2013年 itcast. All rights reserved.
- #import <QuartzCore/QuartzCore.h>
- #import "MJPhotoBrowser.h"
- #import "MJPhoto.h"
- #import "MJPhotoView.h"
- #import "MJPhotoToolbar.h"
- #import <SDWebImagePrefetcher.h>
- #define kPadding 10
- #define kPhotoViewTagOffset 1000
- #define kPhotoViewIndex(photoView) ([photoView tag] - kPhotoViewTagOffset)
- @interface MJPhotoBrowser () <MJPhotoViewDelegate>
- {
- // 滚动的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
|