// // NewPhotoPreviewController.m // RA Image // // Created by Jack on 2017/6/14. // Copyright © 2017年 USAI. All rights reserved. // #import "RAPhotoPreviewController.h" #import "PhotoPreviewCell.h" @interface RAPhotoItemPlaceHolder : NSObject @property (nonatomic,weak) id model; @property (nonatomic,weak) id delegate; @property (nonatomic,strong) UIImage *image; @end @implementation RAPhotoItemPlaceHolder - (instancetype)initWithModel:(id)model { if (self = [super init]) { self.model = model; } return self; } - (UIImage *)image { return self.model.image; } @end #pragma mark - VC @interface RAPhotoPreviewController () @property (nonatomic,assign) NSUInteger currentIndex; @property (strong, nonatomic) IBOutlet UILabel *indicator; @property (strong, nonatomic) IBOutlet UICollectionView *previewContainer; @property (nonatomic,strong) NSArray> *photos; @property (nonatomic,assign) NSUInteger offset; @property (nonatomic,assign) NSUInteger photoCount; @property (nonatomic,assign) BOOL hideNavigationBar; @property (nonatomic,assign) BOOL initialized; @end @implementation RAPhotoPreviewController + (instancetype)ra_photoPreviewControllerWithPhotoItems:(NSArray> *)items offset:(NSUInteger)offset { RAPhotoPreviewController *vc = [[UIStoryboard storyboardWithName:@"PhotoList" bundle:nil] instantiateViewControllerWithIdentifier:@"RAPhotoPreviewController"]; // 只有一张图片时,滑动会将View 和 Model 解绑,并且刷新View,导致看到黑色。 if (items.count == 1) { NSMutableArray> *tmpArr = [NSMutableArray arrayWithArray:items]; id item = items[0]; RAPhotoItemPlaceHolder *placeHolder = [[RAPhotoItemPlaceHolder alloc] initWithModel:item]; [tmpArr addObject:placeHolder]; items = tmpArr; vc.photoCount = 1; } else { vc.photoCount = items.count; } if (offset == 0 || offset >= items.count) { vc.photos = items; } else { NSMutableArray> *tmpArr = [NSMutableArray array]; [tmpArr addObjectsFromArray:[items subarrayWithRange:NSMakeRange(offset, items.count - offset)]]; for (int i = 0; i < offset; i++) { id model = [items objectAtIndex:i]; [tmpArr addObject:model]; } items = [tmpArr copy]; vc.photos = items; } vc.offset = offset; vc.currentIndex = 0; return vc; } - (void)viewDidLoad { [super viewDidLoad]; if (@available(iOS 11, *)) { self.previewContainer.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { self.automaticallyAdjustsScrollViewInsets = NO; } self.indicator.layer.cornerRadius = 20; self.indicator.layer.masksToBounds = YES; self.previewContainer.pagingEnabled = YES; self.hideNavigationBar = self.navigationController.isNavigationBarHidden; self.navigationController.navigationBarHidden = YES; [self updateIndicator]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; [self.previewContainer setContentOffset:CGPointMake((self.currentIndex + 1) * CGRectGetWidth(self.previewContainer.frame), 0) animated:YES]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // 隐藏初始化时滚动效果 self.initialized = YES; [self.previewContainer reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:self.currentIndex + 1 inSection:0]]]; } - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; [coordinator animateAlongsideTransitionInView:self.previewContainer animation:^(id _Nonnull context) { // 重新布局 Item 大小 [self.previewContainer.collectionViewLayout invalidateLayout]; } completion:^(id _Nonnull context) { [self.previewContainer reloadData]; }]; } - (BOOL)prefersStatusBarHidden { return YES; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - FlowLayout Delegate - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return collectionView.bounds.size; } - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 0; } - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { return 0; } - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { return UIEdgeInsetsZero; } #pragma mark - CollectionView Delegate - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { if (self.initialized) { NSUInteger idx = [self contentOffsetForIndexPath:indexPath]; PhotoPreviewCell *preCell = (PhotoPreviewCell *)cell; id model = [self.photos objectAtIndex:idx]; // preCell.model = model; } } - (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { PhotoPreviewCell *preCell = (PhotoPreviewCell *)cell; // [preCell reset]; } #pragma mark - CollectionView DataSource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { if ([self.photos count] == 0) { return 0; } return self.photos.count + 2; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { PhotoPreviewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"PhotoPreviewCell" forIndexPath:indexPath]; cell.scrollView.delegate = self; return cell; } #pragma mark - ScrollView Delegate - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView == self.previewContainer) { CGFloat offsetX = scrollView.contentOffset.x; float idxf = offsetX / CGRectGetWidth(scrollView.frame); int idxi = (int)(offsetX / CGRectGetWidth(scrollView.frame)); if (idxf == idxi) { if (idxi == 0) { self.currentIndex = self.photos.count - 1; } else if (idxi == self.photos.count + 1) { self.currentIndex = 0; } else { self.currentIndex = idxi - 1; } [self updateIndicator]; } else { } if (idxi == 0) { [self scrollToIndex:self.photos.count]; } if (idxi == self.photos.count + 1) { [self scrollToIndex:1]; } } } - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { if (scrollView != self.previewContainer) { return scrollView.subviews.firstObject; } return nil; } #pragma mark - Private - (void)updateIndicator { /** x 0 1 2 3 4 5 6 7 8 9 4 5 6 7 8 9 0 1 2 3 */ NSUInteger index = (self.currentIndex + self.offset) % self.photos.count + 1; if (self.photoCount == 1) { index = 1; } NSString *offset = [NSString stringWithFormat:@"%lu / %lu",index,(unsigned long)self.photoCount]; self.indicator.text = offset; } - (NSUInteger)contentOffsetForIndexPath:(NSIndexPath *)indexPath { NSUInteger idx = indexPath.row; if (idx == 0) { idx = self.photos.count - 1; }else if (idx == self.photos.count + 1) { idx = 0; } else { idx = idx - 1; } return idx; } - (void)scrollToIndex:(NSUInteger)index { // 不会出现肉眼可见的滚动效果 self.previewContainer.contentOffset = CGPointMake(index * CGRectGetWidth(self.previewContainer.frame), 0); } - (IBAction)closeBtnClick:(UIButton *)sender { if (self.navigationController) { self.navigationController.navigationBarHidden = self.hideNavigationBar; [self.navigationController popViewControllerAnimated:YES]; } else { [self dismissViewControllerAnimated:YES completion:nil]; } } @end