|
@@ -0,0 +1,231 @@
|
|
|
|
|
+//
|
|
|
|
|
+// NewPhotoPreviewController.m
|
|
|
|
|
+// RA Image
|
|
|
|
|
+//
|
|
|
|
|
+// Created by Jack on 2017/6/14.
|
|
|
|
|
+// Copyright © 2017年 USAI. All rights reserved.
|
|
|
|
|
+//
|
|
|
|
|
+
|
|
|
|
|
+#import "RAPhotoPreviewController.h"
|
|
|
|
|
+#import "PhotoPreviewCell.h"
|
|
|
|
|
+
|
|
|
|
|
+@interface RAPhotoPreviewController ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
|
|
|
|
|
+
|
|
|
|
|
+@property (nonatomic,assign) NSUInteger currentIndex;
|
|
|
|
|
+@property (strong, nonatomic) IBOutlet UILabel *indicator;
|
|
|
|
|
+@property (strong, nonatomic) IBOutlet UICollectionView *previewContainer;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@property (nonatomic,strong) NSArray<id<RAPhotoItemDelegate>> *photos;
|
|
|
|
|
+@property (nonatomic,assign) NSUInteger offset;
|
|
|
|
|
+
|
|
|
|
|
+@property (nonatomic,assign) BOOL hideNavigationBar;
|
|
|
|
|
+
|
|
|
|
|
+@end
|
|
|
|
|
+
|
|
|
|
|
+@implementation RAPhotoPreviewController
|
|
|
|
|
+
|
|
|
|
|
++ (instancetype)ra_photoPreviewControllerWithPhotoItems:(NSArray<id<RAPhotoItemDelegate>> *)items offset:(NSUInteger)offset {
|
|
|
|
|
+
|
|
|
|
|
+ RAPhotoPreviewController *vc = [[UIStoryboard storyboardWithName:@"PhotoList" bundle:nil] instantiateViewControllerWithIdentifier:@"RAPhotoPreviewController"];
|
|
|
|
|
+ if (offset == 0 || offset >= items.count) {
|
|
|
|
|
+ vc.photos = items;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ NSMutableArray<id<RAPhotoItemDelegate>> *tmpArr = [NSMutableArray array];
|
|
|
|
|
+ [tmpArr addObjectsFromArray:[items subarrayWithRange:NSMakeRange(offset, items.count - offset)]];
|
|
|
|
|
+ for (int i = 0; i < offset; i++) {
|
|
|
|
|
+ id<RAPhotoItemDelegate> model = [items objectAtIndex:i];
|
|
|
|
|
+ [tmpArr addObject:model];
|
|
|
|
|
+ }
|
|
|
|
|
+ items = [tmpArr copy];
|
|
|
|
|
+ vc.photos = items;
|
|
|
|
|
+ }
|
|
|
|
|
+ vc.offset = 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;
|
|
|
|
|
+ NSString *offset = [NSString stringWithFormat:@"%lu / %lu",(unsigned long)self.currentIndex + 1,(unsigned long)self.photos.count];
|
|
|
|
|
+ self.indicator.text = offset;
|
|
|
|
|
+
|
|
|
|
|
+ self.hideNavigationBar = self.navigationController.isNavigationBarHidden;
|
|
|
|
|
+
|
|
|
|
|
+ self.navigationController.navigationBarHidden = YES;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (void)viewWillAppear:(BOOL)animated {
|
|
|
|
|
+ [super viewWillAppear:animated];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (void)viewDidLayoutSubviews {
|
|
|
|
|
+ [super viewDidLayoutSubviews];
|
|
|
|
|
+
|
|
|
|
|
+ [self.previewContainer setContentOffset:CGPointMake((self.currentIndex + 1) * CGRectGetWidth(self.previewContainer.frame), 0) animated:NO];
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (void)viewDidAppear:(BOOL)animated {
|
|
|
|
|
+ [super viewDidAppear:animated];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
|
|
|
|
|
+
|
|
|
|
|
+ // 重新布局 Item 大小
|
|
|
|
|
+ [self.previewContainer.collectionViewLayout invalidateLayout];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (BOOL)prefersStatusBarHidden {
|
|
|
|
|
+ return YES;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (void)didReceiveMemoryWarning {
|
|
|
|
|
+ [super didReceiveMemoryWarning];
|
|
|
|
|
+ // Dispose of any resources that can be recreated.
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#pragma mark - Setter
|
|
|
|
|
+
|
|
|
|
|
+- (void)setOffset:(NSUInteger)offset {
|
|
|
|
|
+ [self setCurrentIndex:offset];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#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 {
|
|
|
|
|
+
|
|
|
|
|
+ NSUInteger idx = [self contentOffsetForIndexPath:indexPath];
|
|
|
|
|
+
|
|
|
|
|
+ PhotoPreviewCell *preCell = (PhotoPreviewCell *)cell;
|
|
|
|
|
+
|
|
|
|
|
+ id<RAPhotoItemDelegate> model = [self.photos objectAtIndex:idx];
|
|
|
|
|
+ preCell.model = model;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#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 {
|
|
|
|
|
+ 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;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
|
|
|
|
|
+
|
|
|
|
|
+ if (self.previewContainer != scrollView) {
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#pragma mark - Private
|
|
|
|
|
+
|
|
|
|
|
+- (void)updateIndicator {
|
|
|
|
|
+ NSString *offset = [NSString stringWithFormat:@"%lu / %lu",(unsigned long)self.currentIndex + 1,(unsigned long)self.photos.count];
|
|
|
|
|
+ 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
|