diff --git a/GMGridView/GMGridView.h b/GMGridView/GMGridView.h index 6dff876..91a9834 100644 --- a/GMGridView/GMGridView.h +++ b/GMGridView/GMGridView.h @@ -94,6 +94,10 @@ typedef enum // Cells - (GMGridViewCell *)cellForItemAtIndex:(NSInteger)position; // Might return nil if cell not loaded yet +- (void)openTransformAtIndex:(NSInteger)position; +- (void)closeTransform; +- (BOOL)isInTransformingState; + // Actions - (void)reloadData; - (void)insertObjectAtIndex:(NSInteger)index animated:(BOOL)animated; @@ -185,6 +189,8 @@ typedef enum @optional - (void)GMGridView:(GMGridView *)gridView didStartTransformingCell:(GMGridViewCell *)cell; - (void)GMGridView:(GMGridView *)gridView didEnterFullSizeForCell:(GMGridViewCell *)cell; +- (void)GMGridView:(GMGridView *)gridView willExitFullSizeForCell:(GMGridViewCell *)cell; + - (void)GMGridView:(GMGridView *)gridView didEndTransformingCell:(GMGridViewCell *)cell; @end diff --git a/GMGridView/GMGridView.m b/GMGridView/GMGridView.m index c26877f..e1bec47 100644 --- a/GMGridView/GMGridView.m +++ b/GMGridView/GMGridView.m @@ -838,7 +838,7 @@ - (void)panGestureUpdated:(UIPanGestureRecognizer *)panGesture case UIGestureRecognizerStateFailed: { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(transformingGestureDidFinish) object:nil]; - [self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.1]; + [self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.0]; self.scrollEnabled = YES; @@ -879,7 +879,7 @@ - (void)pinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture case UIGestureRecognizerStateFailed: { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(transformingGestureDidFinish) object:nil]; - [self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.1]; + [self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.0]; break; } @@ -939,7 +939,7 @@ - (void)rotationGestureUpdated:(UIRotationGestureRecognizer *)rotationGesture case UIGestureRecognizerStateFailed: { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(transformingGestureDidFinish) object:nil]; - [self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.1]; + [self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.0]; break; } @@ -963,6 +963,126 @@ - (void)rotationGestureUpdated:(UIRotationGestureRecognizer *)rotationGesture } } } +- (void)startOpenTransformAtIndex:(NSInteger)index +{ + _transformingItem = [self cellForItemAtIndex:index]; + + CGRect frameInMainView = [self convertRect:_transformingItem.frame toView:self.mainSuperView]; + + [_transformingItem removeFromSuperview]; + _transformingItem.frame = self.mainSuperView.bounds; + _transformingItem.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + _transformingItem.contentView.frame = frameInMainView; + [self.mainSuperView addSubview:_transformingItem]; + [self.mainSuperView bringSubviewToFront:_transformingItem]; + + _transformingItem.fullSize = [self.transformDelegate GMGridView:self sizeInFullSizeForCell:_transformingItem atIndex:index inInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; + _transformingItem.fullSizeView = [self.transformDelegate GMGridView:self fullSizeViewForCell:_transformingItem atIndex:index]; + + if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didStartTransformingCell:)]) + { + [self.transformDelegate GMGridView:self didStartTransformingCell:_transformingItem]; + } +} +- (void)completeOpenTransform +{ + _lastRotation = 0; + _lastScale = 1; + + [self bringSubviewToFront:_transformingItem]; + + [_transformingItem prepareContentToFullSize]; + + [UIView animateWithDuration:0.3 + animations:^{ + [_transformingItem transitionContentToFullSize]; + } + completion:^(BOOL finished){ + [self setNeedsLayout]; + if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didEnterFullSizeForCell:)]) + { + [self.transformDelegate GMGridView:self didEnterFullSizeForCell:_transformingItem]; + } + } + ]; + + + _inTransformingState = YES; + _inFullSizeMode = YES; + + // Transfer the gestures on the fullscreen to make is they are accessible (depends on self.mainSuperView) + [_transformingItem.fullSizeView addGestureRecognizer:_pinchGesture]; + [_transformingItem.fullSizeView addGestureRecognizer:_rotationGesture]; + [_transformingItem.fullSizeView addGestureRecognizer:_panGesture]; +} + +- (void)startCloseTransform +{ + _inTransformingState = NO; + [_transformingItem prepareFullSizeToContent]; + + if ([self.transformDelegate respondsToSelector:@selector(GMGridView:willExitFullSizeForCell:)]) + { + [self.transformDelegate GMGridView:self willExitFullSizeForCell:_transformingItem]; + } + + + [UIView animateWithDuration:0.3 + animations:^{ + [_transformingItem transitionFullSizeToContent]; + } + completion:^(BOOL finished){ + [self setNeedsLayout]; + } + ]; +} + +- (void)completeCloseTransform +{ + _lastRotation = 0; + _lastScale = 1.0; + + GMGridViewCell *transformingView = _transformingItem; + _transformingItem = nil; + + NSInteger position = [self positionForItemSubview:transformingView]; + CGPoint origin = [self.layoutStrategy originForItemAtPosition:position]; + + CGRect finalFrameInScroll = CGRectMake(origin.x, origin.y, _itemSize.width, _itemSize.height); + CGRect finalFrameInSuperview = [self convertRect:finalFrameInScroll toView:self.mainSuperView]; + +// [transformingView switchToFullSizeMode:NO]; + transformingView.autoresizingMask = UIViewAutoresizingNone; + [UIView animateWithDuration: kDefaultAnimationDuration + delay:0 + options: kDefaultAnimationOptions + animations:^{ + transformingView.contentView.transform = CGAffineTransformIdentity; + transformingView.contentView.frame = finalFrameInSuperview; + transformingView.backgroundColor = [UIColor clearColor]; + } + completion:^(BOOL finished){ + [transformingView removeFromSuperview]; + transformingView.frame = finalFrameInScroll; + transformingView.contentView.frame = transformingView.bounds; + + transformingView.fullSizeView = nil; + [self addSubview:transformingView]; + + _inFullSizeMode = NO; + + if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didEndTransformingCell:)]) + { + [self.transformDelegate GMGridView:self didEndTransformingCell:transformingView]; + } + + // Transfer the gestures back + [self addGestureRecognizer:_pinchGesture]; + [self addGestureRecognizer:_rotationGesture]; + [self addGestureRecognizer:_panGesture]; + } + ]; +} - (void)transformingGestureDidBeginWithGesture:(UIGestureRecognizer *)gesture { @@ -975,37 +1095,14 @@ - (void)transformingGestureDidBeginWithGesture:(UIGestureRecognizer *)gesture if (_inTransformingState) { - _inTransformingState = NO; - - CGPoint center = _transformingItem.fullSizeView.center; - - [_transformingItem switchToFullSizeMode:NO]; - CGAffineTransform newTransform = CGAffineTransformMakeScale(2.5, 2.5); - _transformingItem.contentView.transform = newTransform; - _transformingItem.contentView.center = center; + [self startCloseTransform]; } else if (!_transformingItem) { CGPoint locationTouch = [gesture locationOfTouch:0 inView:self]; NSInteger positionTouch = [self.layoutStrategy itemPositionFromLocation:locationTouch]; - _transformingItem = [self cellForItemAtIndex:positionTouch]; - - CGRect frameInMainView = [self convertRect:_transformingItem.frame toView:self.mainSuperView]; - - [_transformingItem removeFromSuperview]; - _transformingItem.frame = self.mainSuperView.bounds; - _transformingItem.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _transformingItem.contentView.frame = frameInMainView; - [self.mainSuperView addSubview:_transformingItem]; - [self.mainSuperView bringSubviewToFront:_transformingItem]; - - _transformingItem.fullSize = [self.transformDelegate GMGridView:self sizeInFullSizeForCell:_transformingItem atIndex:positionTouch inInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; - _transformingItem.fullSizeView = [self.transformDelegate GMGridView:self fullSizeViewForCell:_transformingItem atIndex:positionTouch]; - - if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didStartTransformingCell:)]) - { - [self.transformDelegate GMGridView:self didStartTransformingCell:_transformingItem]; - } + + [self startOpenTransformAtIndex:positionTouch]; } } @@ -1019,93 +1116,27 @@ - (void)transformingGestureDidFinish if ([self isInTransformingState]) { if (_lastScale > 2 && !_inTransformingState) - { - _lastRotation = 0; - _lastScale = 1; - - [self bringSubviewToFront:_transformingItem]; - - CGFloat rotationValue = atan2f(_transformingItem.contentView.transform.b, _transformingItem.contentView.transform.a); - - _transformingItem.contentView.transform = CGAffineTransformIdentity; - - [_transformingItem switchToFullSizeMode:YES]; - _transformingItem.backgroundColor = [[UIColor darkGrayColor] colorWithAlphaComponent:0.9]; - - _transformingItem.fullSizeView.transform = CGAffineTransformMakeRotation(rotationValue); - - [UIView animateWithDuration:kDefaultAnimationDuration - delay:0 - options:kDefaultAnimationOptions - animations:^{ - _transformingItem.fullSizeView.transform = CGAffineTransformIdentity; - } - completion:nil - ]; - - _inTransformingState = YES; - _inFullSizeMode = YES; - - if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didEnterFullSizeForCell:)]) - { - [self.transformDelegate GMGridView:self didEnterFullSizeForCell:_transformingItem]; - } - - // Transfer the gestures on the fullscreen to make is they are accessible (depends on self.mainSuperView) - [_transformingItem.fullSizeView addGestureRecognizer:_pinchGesture]; - [_transformingItem.fullSizeView addGestureRecognizer:_rotationGesture]; - [_transformingItem.fullSizeView addGestureRecognizer:_panGesture]; + { + [self completeOpenTransform]; } else if (!_inTransformingState) { - _lastRotation = 0; - _lastScale = 1.0; - - GMGridViewCell *transformingView = _transformingItem; - _transformingItem = nil; - - NSInteger position = [self positionForItemSubview:transformingView]; - CGPoint origin = [self.layoutStrategy originForItemAtPosition:position]; - - CGRect finalFrameInScroll = CGRectMake(origin.x, origin.y, _itemSize.width, _itemSize.height); - CGRect finalFrameInSuperview = [self convertRect:finalFrameInScroll toView:self.mainSuperView]; - - [transformingView switchToFullSizeMode:NO]; - transformingView.autoresizingMask = UIViewAutoresizingNone; - - [UIView animateWithDuration: kDefaultAnimationDuration - delay:0 - options: kDefaultAnimationOptions - animations:^{ - transformingView.contentView.transform = CGAffineTransformIdentity; - transformingView.contentView.frame = finalFrameInSuperview; - transformingView.backgroundColor = [UIColor clearColor]; - } - completion:^(BOOL finished){ - - [transformingView removeFromSuperview]; - transformingView.frame = finalFrameInScroll; - transformingView.contentView.frame = transformingView.bounds; - [self addSubview:transformingView]; - - transformingView.fullSizeView = nil; - _inFullSizeMode = NO; - - if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didEndTransformingCell:)]) - { - [self.transformDelegate GMGridView:self didEndTransformingCell:transformingView]; - } - - // Transfer the gestures back - [self addGestureRecognizer:_pinchGesture]; - [self addGestureRecognizer:_rotationGesture]; - [self addGestureRecognizer:_panGesture]; - } - ]; + [self completeCloseTransform]; } } } +- (void)openTransformAtIndex:(NSInteger)position +{ + [self startOpenTransformAtIndex:position]; + [self completeOpenTransform]; +} +- (void)closeTransform +{ + [self startCloseTransform]; + [self completeCloseTransform]; +} + ////////////////////////////////////////////////////////////// #pragma mark Tap gesture ////////////////////////////////////////////////////////////// diff --git a/GMGridView/GMGridViewCell+Extended.h b/GMGridView/GMGridViewCell+Extended.h index 36230cb..c8fac40 100644 --- a/GMGridView/GMGridViewCell+Extended.h +++ b/GMGridView/GMGridViewCell+Extended.h @@ -58,5 +58,10 @@ typedef void (^GMGridViewCellDeleteBlock)(GMGridViewCell*); - (void)switchToFullSizeMode:(BOOL)fullSizeEnabled; - (void)stepToFullsizeWithAlpha:(CGFloat)alpha; // not supported yet +- (void)prepareContentToFullSize; +- (void)transitionContentToFullSize; + +- (void)prepareFullSizeToContent; +- (void)transitionFullSizeToContent; @end diff --git a/GMGridView/GMGridViewCell.m b/GMGridView/GMGridViewCell.m index cb5504a..d792aa1 100644 --- a/GMGridView/GMGridViewCell.m +++ b/GMGridView/GMGridViewCell.m @@ -250,6 +250,53 @@ - (void)actionDelete ////////////////////////////////////////////////////////////// #pragma mark Public methods ////////////////////////////////////////////////////////////// +- (void)prepareContentToFullSize +{ + // Transfer center, rotation and scale to the full size view + CGFloat rotationValue = atan2f(self.contentView.transform.b, self.contentView.transform.a); + CGFloat sx = self.contentView.frame.size.width / self.fullSizeView.frame.size.width; + CGFloat sy = self.contentView.frame.size.height / self.fullSizeView.frame.size.height; + CGFloat tx = self.contentView.center.x - self.fullSizeView.center.x; + CGFloat ty = self.contentView.center.y - self.fullSizeView.center.y; + + CGAffineTransform transform = CGAffineTransformMakeTranslation(tx,ty); + transform = CGAffineTransformScale(transform, sx, sy); + self.fullSizeView.transform = CGAffineTransformRotate(transform, rotationValue); + + // Reset the resize mask for full screen mode + self.fullSizeView.autoresizingMask = self.defaultFullsizeViewResizingMask; + + // Put the fullsize view at the top alpha level and hide contentView + self.fullSizeView.alpha = MAX(self.fullSizeView.alpha, self.contentView.alpha); + self.contentView.alpha = 0; +} + +- (void)transitionContentToFullSize +{ + // Animate fullSizeView back to it's intended state + CGPoint center = self.fullSizeView.center; + self.fullSizeView.alpha = 1; + self.fullSizeView.transform = CGAffineTransformIdentity; + self.fullSizeView.center = center; + self.fullSizeView.frame = CGRectMake(self.fullSizeView.frame.origin.x, + self.fullSizeView.frame.origin.y, + self.fullSize.width, + self.fullSize.height); +} + +- (void)prepareFullSizeToContent +{ + self.fullSizeView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + + self.fullSizeView.alpha = 0; + self.contentView.alpha = 0.6; +} + +- (void)transitionFullSizeToContent +{ + self.contentView.alpha = 1; + self.fullSizeView.frame = self.bounds; +} - (void)prepareForReuse { @@ -272,45 +319,11 @@ - (void)switchToFullSizeMode:(BOOL)fullSizeEnabled { if (fullSizeEnabled) { - self.fullSizeView.autoresizingMask = self.defaultFullsizeViewResizingMask; - - CGPoint center = self.fullSizeView.center; - self.fullSizeView.frame = CGRectMake(self.fullSizeView.frame.origin.x, self.fullSizeView.frame.origin.y, self.fullSize.width, self.fullSize.height); - self.fullSizeView.center = center; - - _inFullSizeMode = YES; - - self.fullSizeView.alpha = MAX(self.fullSizeView.alpha, self.contentView.alpha); - self.contentView.alpha = 0; - - [UIView animateWithDuration:0.3 - animations:^{ - self.fullSizeView.alpha = 1; - self.fullSizeView.frame = CGRectMake(self.fullSizeView.frame.origin.x, self.fullSizeView.frame.origin.y, self.fullSize.width, self.fullSize.height); - self.fullSizeView.center = center; - } - completion:^(BOOL finished){ - [self setNeedsLayout]; - } - ]; + _inFullSizeMode = YES; } else { - self.fullSizeView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _inFullSizeMode = NO; - self.fullSizeView.alpha = 0; - self.contentView.alpha = 0.6; - - [UIView animateWithDuration:0.3 - animations:^{ - self.contentView.alpha = 1; - self.fullSizeView.frame = self.bounds; - } - completion:^(BOOL finished){ - [self setNeedsLayout]; - } - ]; } }