diff --git a/Classes/IDMPhoto.m b/Classes/IDMPhoto.m index 29481a43..1515c8e7 100644 --- a/Classes/IDMPhoto.m +++ b/Classes/IDMPhoto.m @@ -137,12 +137,12 @@ - (void)loadUnderlyingImageAndNotify { } else if (_photoURL) { // Load async from web (using SDWebImageManager) SDWebImageManager *manager = [SDWebImageManager sharedManager]; - [manager downloadImageWithURL:_photoURL options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) { + [manager loadImageWithURL:_photoURL options:SDWebImageRetryFailed|SDWebImageHandleCookies progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) { CGFloat progress = ((CGFloat)receivedSize)/((CGFloat)expectedSize); if (self.progressUpdateBlock) { self.progressUpdateBlock(progress); } - } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { + } completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) { if (image) { self.underlyingImage = image; [self performSelectorOnMainThread:@selector(imageLoadingComplete) withObject:nil waitUntilDone:NO]; diff --git a/Classes/IDMPhotoBrowser.h b/Classes/IDMPhotoBrowser.h index 6fea898c..fc26c3eb 100644 --- a/Classes/IDMPhotoBrowser.h +++ b/Classes/IDMPhotoBrowser.h @@ -21,11 +21,13 @@ - (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser didDismissAtPageIndex:(NSUInteger)index; - (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser willDismissAtPageIndex:(NSUInteger)index; - (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser didDismissActionSheetWithButtonIndex:(NSUInteger)buttonIndex photoIndex:(NSUInteger)photoIndex; +- (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser deleteButtonDidTappedWithPhotoIndex:(NSUInteger)photoIndex; +- (void)photoBrowser:(IDMPhotoBrowser *)photoBrowser actionButtonDidTappedWithPhotoIndex:(NSUInteger)photoIndex; - (IDMCaptionView *)photoBrowser:(IDMPhotoBrowser *)photoBrowser captionViewForPhotoAtIndex:(NSUInteger)index; @end // IDMPhotoBrowser -@interface IDMPhotoBrowser : UIViewController +@interface IDMPhotoBrowser : UIViewController // Properties @property (nonatomic, strong) id delegate; @@ -41,8 +43,12 @@ // View customization @property (nonatomic) BOOL displayDoneButton; +@property (nonatomic) BOOL displayDeleteButton; @property (nonatomic) BOOL useWhiteBackgroundColor; @property (nonatomic, weak) UIImage *doneButtonImage; +@property (nonatomic, weak) UIColor *doneButtonBorderColor; +@property (nonatomic, weak) UIColor *doneButtonTitleColor; +@property (nonatomic, copy) NSString *doneButtonTitle; @property (nonatomic, weak) UIColor *trackTintColor, *progressTintColor; @property (nonatomic, weak) UIImage *scaleImage; @@ -50,7 +56,6 @@ @property (nonatomic) BOOL arrowButtonsChangePhotosAnimated; @property (nonatomic) BOOL forceHideStatusBar; -@property (nonatomic) BOOL usePopAnimation; @property (nonatomic) BOOL disableVerticalSwipe; // defines zooming of the background (default 1.0) @@ -80,4 +85,7 @@ // Get IDMPhoto at index - (id)photoAtIndex:(NSUInteger)index; +// Delete the photo at index +- (void)deletePhotoAtIndex:(NSUInteger)index; + @end diff --git a/Classes/IDMPhotoBrowser.m b/Classes/IDMPhotoBrowser.m index 66039cc7..b7532411 100644 --- a/Classes/IDMPhotoBrowser.m +++ b/Classes/IDMPhotoBrowser.m @@ -10,8 +10,6 @@ #import "IDMPhotoBrowser.h" #import "IDMZoomingScrollView.h" -#import "pop/POP.h" - #ifndef IDMPhotoBrowserLocalizedStrings #define IDMPhotoBrowserLocalizedStrings(key) \ NSLocalizedStringFromTableInBundle((key), nil, [NSBundle bundleWithPath:[[NSBundle bundleForClass: self.class] pathForResource:@"IDMPBLocalizations" ofType:@"bundle"]], nil) @@ -19,46 +17,45 @@ // Private @interface IDMPhotoBrowser () { - // Data + // Data NSMutableArray *_photos; - // Views - UIScrollView *_pagingScrollView; - + // Views + UIScrollView *_pagingScrollView; + // Gesture UIPanGestureRecognizer *_panGesture; - // Paging + // Paging NSMutableSet *_visiblePages, *_recycledPages; NSUInteger _pageIndexBeforeRotation; NSUInteger _currentPageIndex; - + // Buttons UIButton *_doneButton; - // Toolbar - UIToolbar *_toolbar; - UIBarButtonItem *_previousButton, *_nextButton, *_actionButton; + // Toolbar + UIToolbar *_toolbar; + UIBarButtonItem *_previousButton, *_nextButton, *_actionButton, *_deleteButton; UIBarButtonItem *_counterButton; UILabel *_counterLabel; // Actions UIActionSheet *_actionsSheet; - UIActivityViewController *activityViewController; // Control NSTimer *_controlVisibilityTimer; // Appearance //UIStatusBarStyle _previousStatusBarStyle; - BOOL _statusBarOriginallyHidden; + BOOL _statusBarOriginallyHidden; // Present UIView *_senderViewForAnimation; // Misc BOOL _performingLayout; - BOOL _rotating; + BOOL _rotating; BOOL _viewIsActive; // active as in it's in the view heirarchy BOOL _autoHide; NSInteger _initalPageIndex; @@ -69,15 +66,14 @@ @interface IDMPhotoBrowser () { //UIImage *_backgroundScreenshot; UIWindow *_applicationWindow; - - // iOS 7 + + // iOS 7 UIViewController *_applicationTopViewController; int _previousModalPresentationStyle; } // Private Properties @property (nonatomic, strong) UIActionSheet *actionsSheet; -@property (nonatomic, strong) UIActivityViewController *activityViewController; // Private Methods @@ -120,6 +116,7 @@ - (BOOL)areControlsHidden; // Data - (NSUInteger)numberOfPhotos; - (id)photoAtIndex:(NSUInteger)index; +- (void)deletePhotoAtIndex:(NSUInteger)index; - (UIImage *)imageForPhoto:(id)photo; - (void)loadAdjacentPhotosIfNecessary:(id)photo; - (void)releaseAllUnderlyingPhotos; @@ -130,14 +127,13 @@ - (void)releaseAllUnderlyingPhotos; @implementation IDMPhotoBrowser // Properties -@synthesize displayDoneButton = _displayDoneButton, displayToolbar = _displayToolbar, displayActionButton = _displayActionButton, displayCounterLabel = _displayCounterLabel, useWhiteBackgroundColor = _useWhiteBackgroundColor, doneButtonImage = _doneButtonImage; +@synthesize displayDoneButton = _displayDoneButton, displayToolbar = _displayToolbar, displayActionButton = _displayActionButton, displayDeleteButton = _displayDeleteButton, displayCounterLabel = _displayCounterLabel, useWhiteBackgroundColor = _useWhiteBackgroundColor, doneButtonImage = _doneButtonImage; @synthesize leftArrowImage = _leftArrowImage, rightArrowImage = _rightArrowImage, leftArrowSelectedImage = _leftArrowSelectedImage, rightArrowSelectedImage = _rightArrowSelectedImage; @synthesize displayArrowButton = _displayArrowButton, actionButtonTitles = _actionButtonTitles; @synthesize arrowButtonsChangePhotosAnimated = _arrowButtonsChangePhotosAnimated; @synthesize forceHideStatusBar = _forceHideStatusBar; -@synthesize usePopAnimation = _usePopAnimation; @synthesize disableVerticalSwipe = _disableVerticalSwipe; -@synthesize actionsSheet = _actionsSheet, activityViewController = _activityViewController; +@synthesize actionsSheet = _actionsSheet; @synthesize trackTintColor = _trackTintColor, progressTintColor = _progressTintColor; @synthesize delegate = _delegate; @@ -148,8 +144,8 @@ - (id)init { // Defaults self.hidesBottomBarWhenPushed = YES; _currentPageIndex = 0; - _performingLayout = NO; // Reset on view did appear - _rotating = NO; + _performingLayout = NO; // Reset on view did appear + _rotating = NO; _viewIsActive = NO; _visiblePages = [NSMutableSet new]; _recycledPages = [NSMutableSet new]; @@ -163,13 +159,13 @@ - (id)init { _displayToolbar = YES; _displayActionButton = YES; + _displayDeleteButton = YES; _displayArrowButton = YES; _displayCounterLabel = NO; _forceHideStatusBar = NO; - _usePopAnimation = NO; - _disableVerticalSwipe = NO; - + _disableVerticalSwipe = NO; + _useWhiteBackgroundColor = NO; _leftArrowImage = _rightArrowImage = _leftArrowSelectedImage = _rightArrowSelectedImage = nil; @@ -186,28 +182,32 @@ - (id)init { self.automaticallyAdjustsScrollViewInsets = NO; _applicationWindow = [[[UIApplication sharedApplication] delegate] window]; - - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) - { - self.modalPresentationStyle = UIModalPresentationCustom; - self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + + if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) + { + self.modalPresentationStyle = UIModalPresentationCustom; + self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; self.modalPresentationCapturesStatusBarAppearance = YES; - } - else - { - _applicationTopViewController = [self topviewController]; - _previousModalPresentationStyle = _applicationTopViewController.modalPresentationStyle; - _applicationTopViewController.modalPresentationStyle = UIModalPresentationCurrentContext; - self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; - } - - self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; - + } + else + { + _applicationTopViewController = [self topviewController]; + _previousModalPresentationStyle = _applicationTopViewController.modalPresentationStyle; + _applicationTopViewController.modalPresentationStyle = UIModalPresentationCurrentContext; + self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + } + + self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + // Listen for IDMPhoto notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleIDMPhotoLoadingDidEndNotification:) name:IDMPhoto_LOADING_DID_END_NOTIFICATION object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleDeviceOrientationDidChange:) + name:UIDeviceOrientationDidChangeNotification + object:nil]; } return self; @@ -215,34 +215,34 @@ - (id)init { - (id)initWithPhotos:(NSArray *)photosArray { if ((self = [self init])) { - _photos = [[NSMutableArray alloc] initWithArray:photosArray]; - } - return self; + _photos = [[NSMutableArray alloc] initWithArray:photosArray]; + } + return self; } - (id)initWithPhotos:(NSArray *)photosArray animatedFromView:(UIView*)view { if ((self = [self init])) { - _photos = [[NSMutableArray alloc] initWithArray:photosArray]; + _photos = [[NSMutableArray alloc] initWithArray:photosArray]; _senderViewForAnimation = view; - } - return self; + } + return self; } - (id)initWithPhotoURLs:(NSArray *)photoURLsArray { if ((self = [self init])) { NSArray *photosArray = [IDMPhoto photosWithURLs:photoURLsArray]; - _photos = [[NSMutableArray alloc] initWithArray:photosArray]; - } - return self; + _photos = [[NSMutableArray alloc] initWithArray:photosArray]; + } + return self; } - (id)initWithPhotoURLs:(NSArray *)photoURLsArray animatedFromView:(UIView*)view { if ((self = [self init])) { NSArray *photosArray = [IDMPhoto photosWithURLs:photoURLsArray]; - _photos = [[NSMutableArray alloc] initWithArray:photosArray]; + _photos = [[NSMutableArray alloc] initWithArray:photosArray]; _senderViewForAnimation = view; - } - return self; + } + return self; } - (void)dealloc { @@ -256,11 +256,11 @@ - (void)releaseAllUnderlyingPhotos { } - (void)didReceiveMemoryWarning { - // Release any cached data, images, etc that aren't in use. + // Release any cached data, images, etc that aren't in use. [self releaseAllUnderlyingPhotos]; - [_recycledPages removeAllObjects]; - - // Releases the view if it doesn't have a superview. + [_recycledPages removeAllObjects]; + + // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; } @@ -391,20 +391,11 @@ - (void)performPresentAnimation { CGRect finalImageViewFrame = [self animationFrameForImage:imageFromView presenting:YES scrollView:nil]; - if(_usePopAnimation) - { - [self animateView:resizableImageView - toFrame:finalImageViewFrame - completion:completion]; - } - else - { - [UIView animateWithDuration:_animationDuration animations:^{ - resizableImageView.layer.frame = finalImageViewFrame; - } completion:^(BOOL finished) { - completion(); - }]; - } + [UIView animateWithDuration:_animationDuration animations:^{ + resizableImageView.layer.frame = finalImageViewFrame; + } completion:^(BOOL finished) { + completion(); + }]; } - (void)performCloseAnimationWithScrollView:(IDMZoomingScrollView*)scrollView { @@ -449,20 +440,11 @@ - (void)performCloseAnimationWithScrollView:(IDMZoomingScrollView*)scrollView { CGRect senderViewOriginalFrame = _senderViewForAnimation.superview ? [_senderViewForAnimation.superview convertRect:_senderViewForAnimation.frame toView:nil] : _senderViewOriginalFrame; - if(_usePopAnimation) - { - [self animateView:resizableImageView - toFrame:senderViewOriginalFrame - completion:completion]; - } - else - { - [UIView animateWithDuration:_animationDuration animations:^{ - resizableImageView.layer.frame = senderViewOriginalFrame; - } completion:^(BOOL finished) { - completion(); - }]; - } + [UIView animateWithDuration:_animationDuration animations:^{ + resizableImageView.layer.frame = senderViewOriginalFrame; + } completion:^(BOOL finished) { + completion(); + }]; } - (CGRect)animationFrameForImage:(UIImage *)image presenting:(BOOL)presenting scrollView:(UIScrollView *)scrollView @@ -510,18 +492,18 @@ - (void)prepareForClosePhotoBrowser { - (void)dismissPhotoBrowserAnimated:(BOOL)animated { self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; - + if ([_delegate respondsToSelector:@selector(photoBrowser:willDismissAtPageIndex:)]) [_delegate photoBrowser:self willDismissAtPageIndex:_currentPageIndex]; [self dismissViewControllerAnimated:animated completion:^{ if ([_delegate respondsToSelector:@selector(photoBrowser:didDismissAtPageIndex:)]) [_delegate photoBrowser:self didDismissAtPageIndex:_currentPageIndex]; - - if (SYSTEM_VERSION_LESS_THAN(@"8.0")) - { - _applicationTopViewController.modalPresentationStyle = _previousModalPresentationStyle; - } + + if (SYSTEM_VERSION_LESS_THAN(@"8.0")) + { + _applicationTopViewController.modalPresentationStyle = _previousModalPresentationStyle; + } }]; } @@ -558,21 +540,21 @@ - (UIViewController *)topviewController - (void)viewDidLoad { // View - self.view.backgroundColor = [UIColor colorWithWhite:(_useWhiteBackgroundColor ? 1 : 0) alpha:1]; + self.view.backgroundColor = [UIColor colorWithWhite:(_useWhiteBackgroundColor ? 1 : 0) alpha:1]; self.view.clipsToBounds = YES; - // Setup paging scrolling view - CGRect pagingScrollViewFrame = [self frameForPagingScrollView]; - _pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame]; + // Setup paging scrolling view + CGRect pagingScrollViewFrame = [self frameForPagingScrollView]; + _pagingScrollView = [[UIScrollView alloc] initWithFrame:pagingScrollViewFrame]; //_pagingScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _pagingScrollView.pagingEnabled = YES; - _pagingScrollView.delegate = self; - _pagingScrollView.showsHorizontalScrollIndicator = NO; - _pagingScrollView.showsVerticalScrollIndicator = NO; - _pagingScrollView.backgroundColor = [UIColor clearColor]; + _pagingScrollView.pagingEnabled = YES; + _pagingScrollView.delegate = self; + _pagingScrollView.showsHorizontalScrollIndicator = NO; + _pagingScrollView.showsVerticalScrollIndicator = NO; + _pagingScrollView.backgroundColor = [UIColor clearColor]; _pagingScrollView.contentSize = [self contentSizeForPagingScrollView]; - [self.view addSubview:_pagingScrollView]; + [self.view addSubview:_pagingScrollView]; // Transition animation [self performPresentAnimation]; @@ -595,13 +577,31 @@ - (void)viewDidLoad { [_doneButton addTarget:self action:@selector(doneButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; if(!_doneButtonImage) { - [_doneButton setTitleColor:[UIColor colorWithWhite:0.9 alpha:0.9] forState:UIControlStateNormal|UIControlStateHighlighted]; - [_doneButton setTitle:IDMPhotoBrowserLocalizedStrings(@"Done") forState:UIControlStateNormal]; + if (self.doneButtonTitleColor) { + [_doneButton setTitleColor:self.doneButtonTitleColor forState:UIControlStateNormal]; + [_doneButton setTitleColor:[self.doneButtonTitleColor colorWithAlphaComponent:.8] forState:UIControlStateHighlighted]; + } + else { + [_doneButton setTitleColor:[UIColor colorWithWhite:0.9 alpha:0.9] forState:UIControlStateNormal|UIControlStateHighlighted]; + } + + if (self.doneButtonTitle) { + [_doneButton setTitle:self.doneButtonTitle forState:UIControlStateNormal]; + } + else { + [_doneButton setTitle:IDMPhotoBrowserLocalizedStrings(@"Done") forState:UIControlStateNormal]; + } + [_doneButton.titleLabel setFont:[UIFont boldSystemFontOfSize:11.0f]]; - [_doneButton setBackgroundColor:[UIColor colorWithWhite:0.1 alpha:0.5]]; _doneButton.layer.cornerRadius = 3.0f; - _doneButton.layer.borderColor = [UIColor colorWithWhite:0.9 alpha:0.9].CGColor; _doneButton.layer.borderWidth = 1.0f; + + if (_doneButtonBorderColor) { + _doneButton.layer.borderColor = [self.doneButtonBorderColor CGColor]; + } + else { + _doneButton.layer.borderColor = [UIColor colorWithWhite:0.9 alpha:0.9].CGColor; + } } else { [_doneButton setBackgroundImage:_doneButtonImage forState:UIControlStateNormal]; @@ -651,7 +651,10 @@ - (void)viewDidLoad { _actionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(actionButtonPressed:)]; - + // Delete Button + _deleteButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemTrash + target:self + action:@selector(deleteButtonPressed:)]; // Gesture _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureRecognized:)]; [_panGesture setMinimumNumberOfTouches:1]; @@ -660,7 +663,7 @@ - (void)viewDidLoad { // Update //[self reloadData]; - // Super + // Super [super viewDidLoad]; } @@ -669,13 +672,17 @@ - (void)viewWillAppear:(BOOL)animated { [self reloadData]; // Super - [super viewWillAppear:animated]; + [super viewWillAppear:animated]; // Status Bar _statusBarOriginallyHidden = [UIApplication sharedApplication].statusBarHidden; // Update UI - [self hideControlsAfterDelay]; + [self hideControlsAfterDelay]; + + if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) { + [self handleDeviceOrientationDidChange:nil]; + } } - (void)viewDidAppear:(BOOL)animated { @@ -685,7 +692,7 @@ - (void)viewDidAppear:(BOOL)animated { // Release any retained subviews of the main view. - (void)viewDidUnload { - _currentPageIndex = 0; + _currentPageIndex = 0; _pagingScrollView = nil; _visiblePages = nil; _recycledPages = nil; @@ -722,14 +729,14 @@ - (BOOL)prefersStatusBarHidden { } - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation { - return UIStatusBarAnimationFade; + return UIStatusBarAnimationFade; } #pragma mark - Layout - (void)viewWillLayoutSubviews { - // Flag - _performingLayout = YES; + // Flag + _performingLayout = YES; UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation; @@ -741,32 +748,32 @@ - (void)viewWillLayoutSubviews { // Remember index - NSUInteger indexPriorToLayout = _currentPageIndex; - - // Get paging scroll view frame to determine if anything needs changing - CGRect pagingScrollViewFrame = [self frameForPagingScrollView]; - - // Frame needs changing - _pagingScrollView.frame = pagingScrollViewFrame; - - // Recalculate contentSize based on current orientation - _pagingScrollView.contentSize = [self contentSizeForPagingScrollView]; - - // Adjust frames and configuration of each visible page - for (IDMZoomingScrollView *page in _visiblePages) { + NSUInteger indexPriorToLayout = _currentPageIndex; + + // Get paging scroll view frame to determine if anything needs changing + CGRect pagingScrollViewFrame = [self frameForPagingScrollView]; + + // Frame needs changing + _pagingScrollView.frame = pagingScrollViewFrame; + + // Recalculate contentSize based on current orientation + _pagingScrollView.contentSize = [self contentSizeForPagingScrollView]; + + // Adjust frames and configuration of each visible page + for (IDMZoomingScrollView *page in _visiblePages) { NSUInteger index = PAGE_INDEX(page); - page.frame = [self frameForPageAtIndex:index]; + page.frame = [self frameForPageAtIndex:index]; page.captionView.frame = [self frameForCaptionView:page.captionView atIndex:index]; - [page setMaxMinZoomScalesForCurrentBounds]; - } - - // Adjust contentOffset to preserve page location based on values collected prior to location - _pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:indexPriorToLayout]; - [self didStartViewingPageAtIndex:_currentPageIndex]; // initial + [page setMaxMinZoomScalesForCurrentBounds]; + } + + // Adjust contentOffset to preserve page location based on values collected prior to location + _pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:indexPriorToLayout]; + [self didStartViewingPageAtIndex:_currentPageIndex]; // initial - // Reset - _currentPageIndex = indexPriorToLayout; - _performingLayout = NO; + // Reset + _currentPageIndex = indexPriorToLayout; + _performingLayout = NO; // Super [super viewWillLayoutSubviews]; @@ -777,7 +784,7 @@ - (void)performLayout { _performingLayout = YES; NSUInteger numberOfPhotos = [self numberOfPhotos]; - // Setup pages + // Setup pages [_visiblePages removeAllObjects]; [_recycledPages removeAllObjects]; @@ -817,19 +824,24 @@ - (void)performLayout { [items addObject:_nextButton]; [items addObject:flexSpace]; - if(_displayActionButton) + if (_displayActionButton) { [items addObject:_actionButton]; + } + + if (_displayDeleteButton) { + [items insertObject:_deleteButton atIndex:0]; + } [_toolbar setItems:items]; - [self updateToolbar]; + [self updateToolbar]; // Content offset - _pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:_currentPageIndex]; + _pagingScrollView.contentOffset = [self contentOffsetForPageAtIndex:_currentPageIndex]; [self tilePages]; _performingLayout = NO; - - if(! _disableVerticalSwipe) - [self.view addGestureRecognizer:_panGesture]; + + if(! _disableVerticalSwipe) + [self.view addGestureRecognizer:_panGesture]; } #pragma mark - Data @@ -853,6 +865,22 @@ - (NSUInteger)numberOfPhotos { return _photos[index]; } +- (void)deletePhotoAtIndex:(NSUInteger)index { + IDMZoomingScrollView *page = [self pageDisplayedAtIndex:index]; + [page.captionView removeFromSuperview]; + [page removeFromSuperview]; + + [_photos removeObjectAtIndex:index]; + + if (!_photos.count) { + [self doneButtonPressed:_doneButton]; + } + else { + _currentPageIndex != 0 ? _currentPageIndex-- : _currentPageIndex; + [self reloadData]; + } +} + - (IDMCaptionView *)captionViewForPhotoAtIndex:(NSUInteger)index { IDMCaptionView *captionView = nil; if ([_delegate respondsToSelector:@selector(photoBrowser:captionViewForPhotoAtIndex:)]) { @@ -869,19 +897,19 @@ - (IDMCaptionView *)captionViewForPhotoAtIndex:(NSUInteger)index { } - (UIImage *)imageForPhoto:(id)photo { - if (photo) { - // Get image or obtain in background - if ([photo underlyingImage]) { - return [photo underlyingImage]; - } else { + if (photo) { + // Get image or obtain in background + if ([photo underlyingImage]) { + return [photo underlyingImage]; + } else { [photo loadUnderlyingImageAndNotify]; if ([photo respondsToSelector:@selector(placeholderImage)]) { return [photo placeholderImage]; } - } - } + } + } - return nil; + return nil; } - (void)loadAdjacentPhotosIfNecessary:(id)photo { @@ -927,86 +955,136 @@ - (void)handleIDMPhotoLoadingDidEndNotification:(NSNotification *)notification { } } + +#pragma mark - Device Orientation Change Notification + +- (void)handleDeviceOrientationDidChange:(NSNotification *)notification { + UIDeviceOrientation orientation = [UIDevice currentDevice].orientation; + + switch (orientation) { + case UIDeviceOrientationUnknown: + case UIDeviceOrientationPortraitUpsideDown: + case UIDeviceOrientationFaceUp: + case UIDeviceOrientationFaceDown: + return; + + default: + break; + } + + + CGAffineTransform transform = CGAffineTransformMakeRotation(0); + + BOOL isLandscape = UIDeviceOrientationIsLandscape(orientation); + + if (isLandscape) { + CGFloat delta = (UIDeviceOrientationLandscapeLeft == orientation) ? 1 : -1; + transform = CGAffineTransformMakeRotation(delta * M_PI / 2.); + } + + [[UIApplication sharedApplication] setStatusBarHidden:isLandscape + withAnimation:UIStatusBarAnimationFade]; + + [UIView animateWithDuration:.3 animations:^{ + self.view.transform = transform; + self.view.frame = [UIScreen mainScreen].bounds; + } + completion:^(BOOL finished) { + if (finished) { + + /// 因为弹出的是竖屏的, 所以在横屏隐藏. + UIColor *tintColor = isLandscape ? [UIColor clearColor] : [[UIBarButtonItem appearanceWhenContainedIn:[self class], nil] tintColor]; + + _deleteButton.enabled = !isLandscape; + _deleteButton.tintColor = tintColor; + + _actionButton.enabled = !isLandscape; + _actionButton.tintColor = tintColor; + } + }]; +} + + #pragma mark - Paging - (void)tilePages { - // Calculate which pages should be visible - // Ignore padding as paging bounces encroach on that - // and lead to false page loads - CGRect visibleBounds = _pagingScrollView.bounds; - NSInteger iFirstIndex = (NSInteger) floorf((CGRectGetMinX(visibleBounds)+PADDING*2) / CGRectGetWidth(visibleBounds)); - NSInteger iLastIndex = (NSInteger) floorf((CGRectGetMaxX(visibleBounds)-PADDING*2-1) / CGRectGetWidth(visibleBounds)); + // Calculate which pages should be visible + // Ignore padding as paging bounces encroach on that + // and lead to false page loads + CGRect visibleBounds = _pagingScrollView.bounds; + NSInteger iFirstIndex = (NSInteger) floorf((CGRectGetMinX(visibleBounds)+PADDING*2) / CGRectGetWidth(visibleBounds)); + NSInteger iLastIndex = (NSInteger) floorf((CGRectGetMaxX(visibleBounds)-PADDING*2-1) / CGRectGetWidth(visibleBounds)); if (iFirstIndex < 0) iFirstIndex = 0; if (iFirstIndex > [self numberOfPhotos] - 1) iFirstIndex = [self numberOfPhotos] - 1; if (iLastIndex < 0) iLastIndex = 0; if (iLastIndex > [self numberOfPhotos] - 1) iLastIndex = [self numberOfPhotos] - 1; - - // Recycle no longer needed pages + + // Recycle no longer needed pages NSInteger pageIndex; - for (IDMZoomingScrollView *page in _visiblePages) { + for (IDMZoomingScrollView *page in _visiblePages) { pageIndex = PAGE_INDEX(page); - if (pageIndex < (NSUInteger)iFirstIndex || pageIndex > (NSUInteger)iLastIndex) { - [_recycledPages addObject:page]; + if (pageIndex < (NSUInteger)iFirstIndex || pageIndex > (NSUInteger)iLastIndex) { + [_recycledPages addObject:page]; [page prepareForReuse]; - [page removeFromSuperview]; - IDMLog(@"Removed page at index %i", PAGE_INDEX(page)); - } - } - [_visiblePages minusSet:_recycledPages]; + [page removeFromSuperview]; + IDMLog(@"Removed page at index %i", PAGE_INDEX(page)); + } + } + [_visiblePages minusSet:_recycledPages]; while (_recycledPages.count > 2) // Only keep 2 recycled pages [_recycledPages removeObject:[_recycledPages anyObject]]; - - // Add missing pages - for (NSUInteger index = (NSUInteger)iFirstIndex; index <= (NSUInteger)iLastIndex; index++) { - if (![self isDisplayingPageForIndex:index]) { + + // Add missing pages + for (NSUInteger index = (NSUInteger)iFirstIndex; index <= (NSUInteger)iLastIndex; index++) { + if (![self isDisplayingPageForIndex:index]) { // Add new page - IDMZoomingScrollView *page; + IDMZoomingScrollView *page; page = [[IDMZoomingScrollView alloc] initWithPhotoBrowser:self]; page.backgroundColor = [UIColor clearColor]; page.opaque = YES; - [self configurePage:page forIndex:index]; - [_visiblePages addObject:page]; - [_pagingScrollView addSubview:page]; - IDMLog(@"Added page at index %i", index); + [self configurePage:page forIndex:index]; + [_visiblePages addObject:page]; + [_pagingScrollView addSubview:page]; + IDMLog(@"Added page at index %i", index); // Add caption IDMCaptionView *captionView = [self captionViewForPhotoAtIndex:index]; captionView.frame = [self frameForCaptionView:captionView atIndex:index]; [_pagingScrollView addSubview:captionView]; page.captionView = captionView; - } - } + } + } } - (BOOL)isDisplayingPageForIndex:(NSUInteger)index { - for (IDMZoomingScrollView *page in _visiblePages) - if (PAGE_INDEX(page) == index) return YES; - return NO; + for (IDMZoomingScrollView *page in _visiblePages) + if (PAGE_INDEX(page) == index) return YES; + return NO; } - (IDMZoomingScrollView *)pageDisplayedAtIndex:(NSUInteger)index { - IDMZoomingScrollView *thePage = nil; - for (IDMZoomingScrollView *page in _visiblePages) { - if (PAGE_INDEX(page) == index) { - thePage = page; break; - } - } - return thePage; + IDMZoomingScrollView *thePage = nil; + for (IDMZoomingScrollView *page in _visiblePages) { + if (PAGE_INDEX(page) == index) { + thePage = page; break; + } + } + return thePage; } - (IDMZoomingScrollView *)pageDisplayingPhoto:(id)photo { - IDMZoomingScrollView *thePage = nil; - for (IDMZoomingScrollView *page in _visiblePages) { - if (page.photo == photo) { - thePage = page; break; - } - } - return thePage; + IDMZoomingScrollView *thePage = nil; + for (IDMZoomingScrollView *page in _visiblePages) { + if (page.photo == photo) { + thePage = page; break; + } + } + return thePage; } - (void)configurePage:(IDMZoomingScrollView *)page forIndex:(NSUInteger)index { - page.frame = [self frameForPageAtIndex:index]; + page.frame = [self frameForPageAtIndex:index]; page.tag = PAGE_INDEX_TAG_OFFSET + index; page.photo = [self photoAtIndex:index]; @@ -1018,11 +1096,11 @@ - (void)configurePage:(IDMZoomingScrollView *)page forIndex:(NSUInteger)index { } - (IDMZoomingScrollView *)dequeueRecycledPage { - IDMZoomingScrollView *page = [_recycledPages anyObject]; - if (page) { - [_recycledPages removeObject:page]; - } - return page; + IDMZoomingScrollView *page = [_recycledPages anyObject]; + if (page) { + [_recycledPages removeObject:page]; + } + return page; } // Handle page changes @@ -1067,9 +1145,9 @@ - (CGSize)contentSizeForPagingScrollView { } - (CGPoint)contentOffsetForPageAtIndex:(NSUInteger)index { - CGFloat pageWidth = _pagingScrollView.bounds.size.width; - CGFloat newOffset = index * pageWidth; - return CGPointMake(newOffset, 0); + CGFloat pageWidth = _pagingScrollView.bounds.size.width; + CGFloat newOffset = index * pageWidth; + return CGPointMake(newOffset, 0); } - (BOOL)isLandscape:(UIInterfaceOrientation)orientation @@ -1078,21 +1156,45 @@ - (BOOL)isLandscape:(UIInterfaceOrientation)orientation } - (CGRect)frameForToolbarAtOrientation:(UIInterfaceOrientation)orientation { + CGRect screenBound = self.view.bounds; + CGFloat screenWidth = screenBound.size.width; + CGFloat screenHeight = screenBound.size.height; CGFloat height = 44; + CGFloat bottomIndicator = 34; + BOOL iPhoneX = NO; - if ([self isLandscape:orientation]) + if ([self isLandscape:orientation]) { height = 32; + if (screenWidth == 821 && screenHeight == 375) { + iPhoneX = NO; + } + } + else { + if (screenWidth == 375 && screenHeight == 812) { + iPhoneX = YES; + } + } - return CGRectMake(0, self.view.bounds.size.height - height, self.view.bounds.size.width, height); + if (iPhoneX) { + return CGRectMake(0, self.view.bounds.size.height - height - bottomIndicator, self.view.bounds.size.width, height); + } + else { + return CGRectMake(0, self.view.bounds.size.height - height, self.view.bounds.size.width, height); + } } - (CGRect)frameForDoneButtonAtOrientation:(UIInterfaceOrientation)orientation { CGRect screenBound = self.view.bounds; CGFloat screenWidth = screenBound.size.width; - + CGFloat screenHeight = screenBound.size.height; // if ([self isLandscape:orientation]) screenWidth = screenBound.size.height; - return CGRectMake(screenWidth - 75, 30, 55, 26); + if (screenWidth == 375 && screenHeight == 812) { + return CGRectMake(screenWidth - 75, 54, 55, 26); + } + else { + return CGRectMake(screenWidth - 75, 30, 55, 26); + } } - (CGRect)frameForCaptionView:(IDMCaptionView *)captionView atIndex:(NSUInteger)index { @@ -1128,36 +1230,36 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { - // Hide controls when dragging begins - [self setControlsHidden:YES animated:YES permanent:NO]; + // Hide controls when dragging begins + [self setControlsHidden:YES animated:YES permanent:NO]; } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { - // Update toolbar when page changes - if(! _arrowButtonsChangePhotosAnimated) [self updateToolbar]; + // Update toolbar when page changes + if(! _arrowButtonsChangePhotosAnimated) [self updateToolbar]; } #pragma mark - Toolbar - (void)updateToolbar { // Counter - if ([self numberOfPhotos] > 1) { - _counterLabel.text = [NSString stringWithFormat:@"%lu %@ %lu", (unsigned long)(_currentPageIndex+1), IDMPhotoBrowserLocalizedStrings(@"of"), (unsigned long)[self numberOfPhotos]]; - } else { - _counterLabel.text = nil; - } + if ([self numberOfPhotos] > 1) { + _counterLabel.text = [NSString stringWithFormat:@"%lu %@ %lu", (unsigned long)(_currentPageIndex+1), IDMPhotoBrowserLocalizedStrings(@"of"), (unsigned long)[self numberOfPhotos]]; + } else { + _counterLabel.text = nil; + } - // Buttons - _previousButton.enabled = (_currentPageIndex > 0); - _nextButton.enabled = (_currentPageIndex < [self numberOfPhotos]-1); + // Buttons + _previousButton.enabled = (_currentPageIndex > 0); + _nextButton.enabled = (_currentPageIndex < [self numberOfPhotos]-1); } - (void)jumpToPageAtIndex:(NSUInteger)index { // Change page - if (index < [self numberOfPhotos]) { - CGRect pageFrame = [self frameForPageAtIndex:index]; + if (index < [self numberOfPhotos]) { + CGRect pageFrame = [self frameForPageAtIndex:index]; - if(_arrowButtonsChangePhotosAnimated) + if(_arrowButtonsChangePhotosAnimated) { [_pagingScrollView setContentOffset:CGPointMake(pageFrame.origin.x - PADDING, 0) animated:YES]; } @@ -1166,10 +1268,10 @@ - (void)jumpToPageAtIndex:(NSUInteger)index { _pagingScrollView.contentOffset = CGPointMake(pageFrame.origin.x - PADDING, 0); [self updateToolbar]; } - } - - // Update timer to give more time - [self hideControlsAfterDelay]; + } + + // Update timer to give more time + [self hideControlsAfterDelay]; } - (void)gotoPreviousPage { [self jumpToPageAtIndex:_currentPageIndex-1]; } @@ -1197,29 +1299,29 @@ - (void)setControlsHidden:(BOOL)hidden animated:(BOOL)animated permanent:(BOOL)p for (UIView *v in captionViews) v.alpha = alpha; } completion:^(BOOL finished) {}]; - // Control hiding timer - // Will cancel existing timer but only begin hiding if they are visible - if (!permanent) [self hideControlsAfterDelay]; + // Control hiding timer + // Will cancel existing timer but only begin hiding if they are visible + if (!permanent) [self hideControlsAfterDelay]; [self setNeedsStatusBarAppearanceUpdate]; } - (void)cancelControlHiding { - // If a timer exists then cancel and release - if (_controlVisibilityTimer) { - [_controlVisibilityTimer invalidate]; - _controlVisibilityTimer = nil; - } + // If a timer exists then cancel and release + if (_controlVisibilityTimer) { + [_controlVisibilityTimer invalidate]; + _controlVisibilityTimer = nil; + } } // Enable/disable control visiblity timer - (void)hideControlsAfterDelay { - // return; + // return; if (![self areControlsHidden]) { [self cancelControlHiding]; - _controlVisibilityTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(hideControls) userInfo:nil repeats:NO]; - } + _controlVisibilityTimer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:@selector(hideControls) userInfo:nil repeats:NO]; + } } - (BOOL)areControlsHidden { return (_toolbar.alpha == 0); } @@ -1234,7 +1336,7 @@ - (void)setInitialPageIndex:(NSUInteger)index { if (index >= [self numberOfPhotos]) index = [self numberOfPhotos]-1; _initalPageIndex = index; _currentPageIndex = index; - if ([self isViewLoaded]) { + if ([self isViewLoaded]) { [self jumpToPageAtIndex:index]; if (!_viewIsActive) [self tilePages]; // Force tiling if view is not visible } @@ -1260,38 +1362,9 @@ - (void)actionButtonPressed:(id)sender { if ([self numberOfPhotos] > 0 && [photo underlyingImage]) { if(!_actionButtonTitles) { - // Activity view - NSMutableArray *activityItems = [NSMutableArray arrayWithObject:[photo underlyingImage]]; - if (photo.caption) [activityItems addObject:photo.caption]; - - self.activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; - - __typeof__(self) __weak selfBlock = self; - - if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) - { - [self.activityViewController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) { - [selfBlock hideControlsAfterDelay]; - selfBlock.activityViewController = nil; - }]; - } - else - { - [self.activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed) { - [selfBlock hideControlsAfterDelay]; - selfBlock.activityViewController = nil; - }]; - } - - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { - [self presentViewController:self.activityViewController animated:YES completion:nil]; - } - else { // iPad - UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:self.activityViewController]; - [popover presentPopoverFromRect:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/4, 0, 0) - inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny - animated:YES]; - } + if ([self.delegate respondsToSelector:@selector(photoBrowser:actionButtonDidTappedWithPhotoIndex:)]) { + [self.delegate photoBrowser:self actionButtonDidTappedWithPhotoIndex:_currentPageIndex]; + } } else { @@ -1306,7 +1379,7 @@ - (void)actionButtonPressed:(id)sender { self.actionsSheet.actionSheetStyle = UIActionSheetStyleBlackTranslucent; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { - [_actionsSheet showInView:self.view]; + [_actionsSheet showInView:self.view]; } else { [_actionsSheet showFromBarButtonItem:sender animated:YES]; } @@ -1317,6 +1390,12 @@ - (void)actionButtonPressed:(id)sender { } } +- (void)deleteButtonPressed:(id)sender { + if ([self.delegate respondsToSelector:@selector(photoBrowser:deleteButtonDidTappedWithPhotoIndex:)]) { + [self.delegate photoBrowser:self deleteButtonDidTappedWithPhotoIndex:_currentPageIndex]; + } +} + #pragma mark - Action Sheet Delegate - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { @@ -1334,22 +1413,4 @@ - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSIn [self hideControlsAfterDelay]; // Continue as normal... } -#pragma mark - pop Animation - -- (void)animateView:(UIView *)view toFrame:(CGRect)frame completion:(void (^)(void))completion -{ - POPSpringAnimation *animation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewFrame]; - [animation setSpringBounciness:6]; - [animation setDynamicsMass:1]; - [animation setToValue:[NSValue valueWithCGRect:frame]]; - [view pop_addAnimation:animation forKey:nil]; - - if (completion) - { - [animation setCompletionBlock:^(POPAnimation *animation, BOOL finished) { - completion(); - }]; - } -} - @end diff --git a/Demo/PhotoBrowserDemo/Menu.m b/Demo/PhotoBrowserDemo/Menu.m index b6dc6414..9732108c 100644 --- a/Demo/PhotoBrowserDemo/Menu.m +++ b/Demo/PhotoBrowserDemo/Menu.m @@ -113,7 +113,7 @@ - (void)buttonWithImageOnScreenPressed:(id)sender browser.displayActionButton = NO; browser.displayArrowButton = YES; browser.displayCounterLabel = YES; - browser.usePopAnimation = YES; +// browser.usePopAnimation = YES; browser.scaleImage = buttonSender.currentImage; if(buttonSender.tag == 102) browser.useWhiteBackgroundColor = YES; diff --git a/IDMPhotoBrowser.podspec b/IDMPhotoBrowser.podspec index 8fbb0bcb..8430af6b 100644 --- a/IDMPhotoBrowser.podspec +++ b/IDMPhotoBrowser.podspec @@ -13,5 +13,4 @@ Pod::Spec.new do |s| s.requires_arc = true s.dependency 'SDWebImage' s.dependency 'DACircularProgress' - s.dependency 'pop' end