Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Minor changes and cleanup

  • Loading branch information...
commit 4cf9e4188ec6e30c0fbbf78109f99575516324c1 1 parent bc02152
@gmoledina authored
View
28 GMGridView.xcodeproj/project.pbxproj
@@ -7,6 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
+ 16026C0E1454628800093AFF /* UIView+GMGridViewShake.m in Sources */ = {isa = PBXBuildFile; fileRef = 16026C0D1454628800093AFF /* UIView+GMGridViewShake.m */; };
+ 16026C131454631600093AFF /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 16026C111454631600093AFF /* LICENSE */; };
+ 16026C141454631600093AFF /* README in Resources */ = {isa = PBXBuildFile; fileRef = 16026C121454631600093AFF /* README */; };
16275EF2144D26C10041AF02 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16275EF1144D26C10041AF02 /* QuartzCore.framework */; };
1691D7A41442CFC300F472BF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1691D7A31442CFC300F472BF /* main.m */; };
1691D7AA1442D01F00F472BF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1691D7A71442D01F00F472BF /* AppDelegate.m */; };
@@ -15,11 +18,14 @@
16924B0C144156FE00E6E556 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16924B0B144156FE00E6E556 /* UIKit.framework */; };
16924B0E144156FE00E6E556 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16924B0D144156FE00E6E556 /* Foundation.framework */; };
16924B10144156FE00E6E556 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 16924B0F144156FE00E6E556 /* CoreGraphics.framework */; };
- 16A0D0291452A8BD004D7BBC /* UIView+GMGridViewShake.m in Sources */ = {isa = PBXBuildFile; fileRef = 16A0D0281452A8BD004D7BBC /* UIView+GMGridViewShake.m */; };
16A0D030145342F8004D7BBC /* GMGridViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 16A0D02F145342F8004D7BBC /* GMGridViewCell.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 16026C0C1454628800093AFF /* UIView+GMGridViewShake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIView+GMGridViewShake.h"; path = "GMGridView/API/UIView+GMGridViewShake.h"; sourceTree = SOURCE_ROOT; };
+ 16026C0D1454628800093AFF /* UIView+GMGridViewShake.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIView+GMGridViewShake.m"; path = "GMGridView/API/UIView+GMGridViewShake.m"; sourceTree = SOURCE_ROOT; };
+ 16026C111454631600093AFF /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
+ 16026C121454631600093AFF /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
16275EF1144D26C10041AF02 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
1691D7A01442CFA800F472BF /* GMGridView-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GMGridView-Info.plist"; path = "GMGridView/GMGridView-Info.plist"; sourceTree = SOURCE_ROOT; };
1691D7A21442CFC300F472BF /* GMGridView-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GMGridView-Prefix.pch"; path = "GMGridView/GMGridView-Prefix.pch"; sourceTree = SOURCE_ROOT; };
@@ -34,8 +40,6 @@
16924B0B144156FE00E6E556 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
16924B0D144156FE00E6E556 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
16924B0F144156FE00E6E556 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
- 16A0D0271452A8BD004D7BBC /* UIView+GMGridViewShake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+GMGridViewShake.h"; sourceTree = SOURCE_ROOT; };
- 16A0D0281452A8BD004D7BBC /* UIView+GMGridViewShake.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+GMGridViewShake.m"; sourceTree = SOURCE_ROOT; };
16A0D02E145342F8004D7BBC /* GMGridViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GMGridViewCell.h; path = GMGridView/API/GMGridViewCell.h; sourceTree = SOURCE_ROOT; };
16A0D02F145342F8004D7BBC /* GMGridViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GMGridViewCell.m; path = GMGridView/API/GMGridViewCell.m; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
@@ -55,11 +59,21 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 16026C10145462EC00093AFF /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ 16026C111454631600093AFF /* LICENSE */,
+ 16026C121454631600093AFF /* README */,
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
16924AFC144156FD00E6E556 = {
isa = PBXGroup;
children = (
16924B11144156FE00E6E556 /* Demo */,
16924B361442CA9400E6E556 /* API */,
+ 16026C10145462EC00093AFF /* Documentation */,
16924B0A144156FE00E6E556 /* Frameworks */,
16924B08144156FE00E6E556 /* Products */,
);
@@ -114,8 +128,8 @@
1691D7AD1442D02C00F472BF /* GMGridView.m */,
16A0D02E145342F8004D7BBC /* GMGridViewCell.h */,
16A0D02F145342F8004D7BBC /* GMGridViewCell.m */,
- 16A0D0271452A8BD004D7BBC /* UIView+GMGridViewShake.h */,
- 16A0D0281452A8BD004D7BBC /* UIView+GMGridViewShake.m */,
+ 16026C0C1454628800093AFF /* UIView+GMGridViewShake.h */,
+ 16026C0D1454628800093AFF /* UIView+GMGridViewShake.m */,
);
name = API;
path = DraggableGridView/API;
@@ -172,6 +186,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 16026C131454631600093AFF /* LICENSE in Resources */,
+ 16026C141454631600093AFF /* README in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -186,8 +202,8 @@
1691D7AA1442D01F00F472BF /* AppDelegate.m in Sources */,
1691D7AB1442D01F00F472BF /* ViewController.m in Sources */,
1691D7AE1442D02C00F472BF /* GMGridView.m in Sources */,
- 16A0D0291452A8BD004D7BBC /* UIView+GMGridViewShake.m in Sources */,
16A0D030145342F8004D7BBC /* GMGridViewCell.m in Sources */,
+ 16026C0E1454628800093AFF /* UIView+GMGridViewShake.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
47 GMGridView/API/GMGridView.h
@@ -5,23 +5,25 @@
// Created by Gulam Moledina on 11-10-09.
// Copyright (C) 2011 by Gulam Moledina.
//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
+// Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
//
#import <UIKit/UIKit.h>
@@ -38,7 +40,7 @@ typedef enum
//////////////////////////////////////////////////////////////
-#pragma mark Interface DraggableGridView
+#pragma mark Interface GMGridView
//////////////////////////////////////////////////////////////
@interface GMGridView : UIView
@@ -65,7 +67,7 @@ typedef enum
//////////////////////////////////////////////////////////////
-#pragma mark Protocol DraggableGridViewDataSource
+#pragma mark Protocol GMGridViewDataSource
//////////////////////////////////////////////////////////////
@protocol GMGridViewDataSource
@@ -76,6 +78,10 @@ typedef enum
- (UIView *)GMGridView:(GMGridView *)gridView viewForItemAtIndex:(NSInteger)index;
- (void)GMGridView:(GMGridView *)gridView itemAtIndex:(NSInteger)oldIndex movedToIndex:(NSInteger)newIndex;
+//@optional
+- (CGSize)GMGridView:(GMGridView *)gridView fullSizeForView:(UIView *)view;
+- (UIView *)GMGridView:(GMGridView *)gridView fullSizeViewForView:(UIView *)view;
+
@end
@@ -92,12 +98,15 @@ typedef enum
@end
//////////////////////////////////////////////////////////////
-#pragma mark Protocol DraggableGridViewTransformationDelegate
+#pragma mark Protocol GMGridViewTransformationDelegate
//////////////////////////////////////////////////////////////
@protocol GMGridViewTransformationDelegate
- (void)GMGridView:(GMGridView *)gridView didStartTransformingView:(UIView *)view;
-- (void)GMGridView:(GMGridView *)gridView didEndTransformingView:(UIView *)view inFullsize:(BOOL)fullSize;
+- (void)GMGridView:(GMGridView *)gridView didEnterFullSizeForView:(UIView *)view;
+- (void)GMGridView:(GMGridView *)gridView didEndTransformingView:(UIView *)view;
+
+
@end
View
284 GMGridView/API/GMGridView.m
@@ -5,23 +5,25 @@
// Created by Gulam Moledina on 11-10-09.
// Copyright (C) 2011 by Gulam Moledina.
//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
+// Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
//
#import <Quartzcore/QuartzCore.h>
@@ -68,12 +70,13 @@ @interface GMGridView () <UIGestureRecognizerDelegate>
GMGridViewCell *_transformingItem;
CGFloat _lastRotation;
CGFloat _lastScale;
+ BOOL _inFullSizeMode;
}
// Gestures
- (void)sortingPanGestureUpdated:(UIPanGestureRecognizer *)panGesture;
- (void)sortingLongPressGestureUpdated:(UILongPressGestureRecognizer *)longPressGesture;
-- (void)tagGestureUpdated:(UITapGestureRecognizer *)tapGesture;
+- (void)tapGestureUpdated:(UITapGestureRecognizer *)tapGesture;
- (void)panGestureUpdated:(UIPanGestureRecognizer *)panGesture;
- (void)pinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture;
- (void)rotationGestureUpdated:(UIRotationGestureRecognizer *)rotationGesture;
@@ -86,8 +89,10 @@ - (void)sortingAutoScrollMovementCheck;
- (void)updateIndexOfItem:(UIView *)view toIndex:(NSInteger)index;
// Transformation control
+- (void)transformingGestureDidBeginWithGesture:(UIGestureRecognizer *)gesture;
- (void)transformingGestureDidFinish;
- (BOOL)isInTransformingState;
+- (void)exitFullSizePinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture;
// Helpers & more
- (CGSize)relayoutItems;
@@ -98,13 +103,10 @@ - (GMGridViewCell *)itemSubViewForPosition:(NSInteger)position;
- (GMGridViewCell *)createItemSubViewForPosition:(NSInteger)position;
- (NSInteger)positionForItemSubview:(GMGridViewCell *)view;
-
-
@end
-
//////////////////////////////////////////////////////////////
#pragma -
#pragma mark Implementation
@@ -136,7 +138,7 @@ - (id)initWithFrame:(CGRect)frame
_scrollView.backgroundColor = [UIColor clearColor];
[self addSubview:_scrollView];
- _tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tagGestureUpdated:)];
+ _tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureUpdated:)];
_tapGesture.delegate = self;
_tapGesture.numberOfTapsRequired = 1;
_tapGesture.numberOfTouchesRequired = 1;
@@ -197,20 +199,6 @@ - (void)layoutSubviews
//////////////////////////////////////////////////////////////
-#pragma mark Custom drawing
-//////////////////////////////////////////////////////////////
-
-//+ (Class)layerClass
-//{
-// return [CATiledLayer class];
-//}
-
-//- (void)drawRect:(CGRect)rect
-//{
-//}
-
-
-//////////////////////////////////////////////////////////////
#pragma mark Setters / getters
//////////////////////////////////////////////////////////////
@@ -438,15 +426,7 @@ - (void)panGestureUpdated:(UIPanGestureRecognizer *)panGesture
}
case UIGestureRecognizerStateBegan:
{
- if (!_transformingItem)
- {
- CGPoint locationTouch = [_pinchGesture locationOfTouch:0 inView:_scrollView];
- NSInteger positionTouch = [self itemPositionFromLocation:locationTouch];
- _transformingItem = [self itemSubViewForPosition:positionTouch];
-
- [_scrollView bringSubviewToFront:_transformingItem];
- [self.transformDelegate GMGridView:self didStartTransformingView:_transformingItem.contentView];
- }
+ [self transformingGestureDidBeginWithGesture:panGesture];
_scrollView.scrollEnabled = NO;
}
@@ -471,8 +451,6 @@ - (void)pinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
{
- _lastScale = 1.0;
-
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(transformingGestureDidFinish) object:nil];
[self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.1];
@@ -480,20 +458,11 @@ - (void)pinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture
}
case UIGestureRecognizerStateBegan:
{
- if (!_transformingItem)
- {
- CGPoint locationTouch = [_pinchGesture locationOfTouch:0 inView:_scrollView];
- NSInteger positionTouch = [self itemPositionFromLocation:locationTouch];
- _transformingItem = [self itemSubViewForPosition:positionTouch];
-
- [_scrollView bringSubviewToFront:_transformingItem];
- [self.transformDelegate GMGridView:self didStartTransformingView:_transformingItem.contentView];
- }
+ [self transformingGestureDidBeginWithGesture:pinchGesture];
}
case UIGestureRecognizerStateChanged:
- default:
{
- if ([_pinchGesture scale] >= 0.5 && [_pinchGesture scale] <= 3)
+ if ([_pinchGesture scale] >= 0.5 && [_pinchGesture scale] <= 2.5)
{
CGFloat scale = ([_pinchGesture scale] - _lastScale) + 1;
@@ -502,10 +471,18 @@ - (void)pinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture
_transformingItem.transform = newTransform;
_lastScale = [_pinchGesture scale];
+
+ if ([_pinchGesture scale] >= 1.5)
+ {
+ [_transformingItem stepToFullsizeWithAlpha:1 - (2.5 - [_pinchGesture scale])];
+ }
}
break;
}
+ default:
+ {
+ }
}
}
@@ -517,8 +494,6 @@ - (void)rotationGestureUpdated:(UIRotationGestureRecognizer *)rotationGesture
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed:
{
- _lastRotation = 0;
-
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(transformingGestureDidFinish) object:nil];
[self performSelector:@selector(transformingGestureDidFinish) withObject:nil afterDelay:0.1];
@@ -526,18 +501,9 @@ - (void)rotationGestureUpdated:(UIRotationGestureRecognizer *)rotationGesture
}
case UIGestureRecognizerStateBegan:
{
- if (!_transformingItem)
- {
- CGPoint locationTouch = [_rotationGesture locationOfTouch:0 inView:_scrollView];
- NSInteger positionTouch = [self itemPositionFromLocation:locationTouch];
- _transformingItem = [self itemSubViewForPosition:positionTouch];
-
- [_scrollView bringSubviewToFront:_transformingItem];
- [self.transformDelegate GMGridView:self didStartTransformingView:_transformingItem.contentView];
- }
+ [self transformingGestureDidBeginWithGesture:rotationGesture];
}
case UIGestureRecognizerStateChanged:
- default:
{
CGFloat rotation = [rotationGesture rotation] - _lastRotation;
CGAffineTransform currentTransform = [_transformingItem transform];
@@ -546,23 +512,69 @@ - (void)rotationGestureUpdated:(UIRotationGestureRecognizer *)rotationGesture
_lastRotation = [rotationGesture rotation];
break;
}
+ default:
+ {
+ }
}
}
-- (void)tagGestureUpdated:(UITapGestureRecognizer *)tapGesture
+
+- (void)transformingGestureDidBeginWithGesture:(UIGestureRecognizer *)gesture
{
- CGPoint locationTouch = [_tapGesture locationInView:_scrollView];
- NSInteger position = [self itemPositionFromLocation:locationTouch];
-
- if (position != GMGV_INVALID_POSITION)
+ if (!_transformingItem)
{
- NSLog(@"Did tap at index %d", position);
+ CGPoint locationTouch = [gesture locationOfTouch:0 inView:_scrollView];
+ NSInteger positionTouch = [self itemPositionFromLocation:locationTouch];
+ _transformingItem = [self itemSubViewForPosition:positionTouch];
+
+
+ CGRect frameInMainView = [_scrollView convertRect:_transformingItem.frame toView:self];
+
+ [_transformingItem removeFromSuperview];
+ _transformingItem.frame = frameInMainView;
+ [self addSubview:_transformingItem];
+ [self bringSubviewToFront:_transformingItem];
+
+ if (!_transformingItem.fullSizeView)
+ {
+ _transformingItem.fullSize = [self.dataSource GMGridView:self fullSizeForView:_transformingItem.contentView];
+ _transformingItem.fullSizeView = [self.dataSource GMGridView:self fullSizeViewForView:_transformingItem];
+ }
+
+ [self.transformDelegate GMGridView:self didStartTransformingView:_transformingItem.contentView];
}
}
-//////////////////////////////////////////////////////////////
-#pragma mark Privates Movement control
-//////////////////////////////////////////////////////////////
+- (void)exitFullSizePinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture
+{
+ if([self isInTransformingState] && _inFullSizeMode)
+ {
+ switch (pinchGesture.state)
+ {
+ case UIGestureRecognizerStateChanged:
+ {
+ if ([pinchGesture scale] < 1.0)
+ {
+ _inFullSizeMode = NO;
+ [_transformingItem removeGestureRecognizer:pinchGesture];
+
+ _transformingItem.frame = _transformingItem.fullSizeView.frame;
+
+ [self transformingGestureDidFinish];
+ break;
+ }
+ }
+ case UIGestureRecognizerStateEnded:
+ case UIGestureRecognizerStateCancelled:
+ case UIGestureRecognizerStateFailed:
+ case UIGestureRecognizerStateBegan:
+ default:
+ {
+ break;
+ }
+ }
+ }
+}
- (BOOL)isInTransformingState
{
@@ -573,25 +585,84 @@ - (void)transformingGestureDidFinish
{
if ([self isInTransformingState])
{
- GMGridViewCell *transformingView = _transformingItem;
- _transformingItem = nil;
-
- NSInteger position = [self positionForItemSubview:transformingView];
- CGPoint origin = [self originForItemAtPosition:position];
-
- [UIView animateWithDuration:0.3
- animations:^{
- transformingView.transform = CGAffineTransformIdentity;
- transformingView.frame = CGRectMake(origin.x, origin.y, _itemSize.width, _itemSize.height);
- }
- completion:^(BOOL finished){
- [self relayoutItems];
- [self.transformDelegate GMGridView:self didEndTransformingView:transformingView.contentView inFullsize:NO];
- }
- ];
+ if (_lastScale > 2)
+ {
+ _lastRotation = 0;
+ _lastScale = 1.0;
+
+ [self bringSubviewToFront:_transformingItem];
+
+ UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(exitFullSizePinchGestureUpdated:)];
+ [_transformingItem addGestureRecognizer:pinch];
+
+ _transformingItem.transform = CGAffineTransformIdentity;
+ [_transformingItem switchToFullSizeMode:YES];
+
+ [UIView animateWithDuration:0.3
+ animations:^{
+ _transformingItem.frame = self.bounds;
+ }
+ completion:^(BOOL finished){
+ _transformingItem.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ _inFullSizeMode = YES;
+ [self.transformDelegate GMGridView:self didEnterFullSizeForView:_transformingItem.contentView];
+ }
+ ];
+ }
+ else
+ {
+ _lastRotation = 0;
+ _lastScale = 1.0;
+
+ GMGridViewCell *transformingView = _transformingItem;
+ _transformingItem = nil;
+
+ transformingView.transform = CGAffineTransformIdentity;
+
+ CGRect frameInScroll = [self convertRect:transformingView.frame toView:_scrollView];
+
+ [transformingView removeFromSuperview];
+ transformingView.frame = frameInScroll;
+ [_scrollView addSubview:transformingView];
+
+ NSInteger position = [self positionForItemSubview:transformingView];
+ CGPoint origin = [self originForItemAtPosition:position];
+
+ [transformingView switchToFullSizeMode:NO];
+ transformingView.autoresizingMask = UIViewAutoresizingNone;
+
+ [UIView animateWithDuration:0.3
+ animations:^{
+ transformingView.frame = CGRectMake(origin.x, origin.y, _itemSize.width, _itemSize.height);
+ }
+ completion:^(BOOL finished){
+ [self relayoutItems];
+ [self.transformDelegate GMGridView:self didEndTransformingView:transformingView.contentView];
+ }
+ ];
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////
+#pragma mark
+//////////////////////////////////////////////////////////////
+
+- (void)tapGestureUpdated:(UITapGestureRecognizer *)tapGesture
+{
+ CGPoint locationTouch = [_tapGesture locationInView:_scrollView];
+ NSInteger position = [self itemPositionFromLocation:locationTouch];
+
+ if (position != GMGV_INVALID_POSITION)
+ {
+ NSLog(@"Did tap at index %d", position);
}
}
+//////////////////////////////////////////////////////////////
+#pragma mark Privates Movement control
+//////////////////////////////////////////////////////////////
+
- (void)sortingMoveDidStartAtPoint:(CGPoint)point
{
NSInteger position = [self itemPositionFromLocation:point];
@@ -621,7 +692,6 @@ - (void)sortingMoveDidStartAtPoint:(CGPoint)point
}
}
-
- (void)sortingMoveDidStopAtPoint:(CGPoint)point
{
[_sortMovingItem shake:NO];
@@ -636,7 +706,6 @@ - (void)sortingMoveDidStopAtPoint:(CGPoint)point
_sortMovingItem.frame.size.height);
[_sortMovingItem removeFromSuperview];
-
_sortMovingItem.frame = frameInScroll;
[_scrollView addSubview:_sortMovingItem];
@@ -658,7 +727,6 @@ - (void)sortingMoveDidStopAtPoint:(CGPoint)point
];
}
-
- (void)sortingMoveDidContinueToPoint:(CGPoint)point
{
int position = [self itemPositionFromLocation:point];
@@ -754,7 +822,7 @@ - (void)reloadData
}
- (void)reloadObjectAtIndex:(NSInteger)index
-{
+{
NSAssert((index >= 0 && index < _numberTotalItems), @"Invalid index");
UIView *currentView = [self itemSubViewForPosition:index];
@@ -764,6 +832,7 @@ - (void)reloadObjectAtIndex:(NSInteger)index
cell.alpha = 0;
[_scrollView addSubview:cell];
+ currentView.tag = GMGV_TAG_OFFSET - 1;
[UIView animateWithDuration:0.3
delay:0
@@ -771,11 +840,14 @@ - (void)reloadObjectAtIndex:(NSInteger)index
animations:^{
currentView.alpha = 0;
cell.alpha = 1;
+
}
completion:^(BOOL finished){
[currentView removeFromSuperview];
}
];
+
+ [_scrollView scrollRectToVisible:cell.frame animated:YES];
}
- (void)insertObjectAtIndex:(NSInteger)index
@@ -812,6 +884,8 @@ - (void)removeObjectAtIndex:(NSInteger)index
oldView.tag = oldView.tag - 1;
}
+ cell.tag = GMGV_TAG_OFFSET - 1;
+
[UIView animateWithDuration:0.2
delay:0
options:0
@@ -824,6 +898,8 @@ - (void)removeObjectAtIndex:(NSInteger)index
[self setNeedsLayout];
}
];
+
+ [_scrollView scrollRectToVisible:cell.frame animated:YES];
}
- (void)swapObjectAtIndex:(NSInteger)index1 withObjectAtIndex:(NSInteger)index2
@@ -838,6 +914,20 @@ - (void)swapObjectAtIndex:(NSInteger)index1 withObjectAtIndex:(NSInteger)index2
view1.tag = view2.tag;
view2.tag = tempTag;
+ CGRect visibleRect = CGRectMake(_scrollView.contentOffset.x,
+ _scrollView.contentOffset.y,
+ _scrollView.contentSize.width,
+ _scrollView.contentSize.height);
+
+ if (!CGRectIntersectsRect(view2.frame, visibleRect))
+ {
+ [_scrollView scrollRectToVisible:view1.frame animated:YES];
+ }
+ else if (!CGRectIntersectsRect(view1.frame, visibleRect))
+ {
+ [_scrollView scrollRectToVisible:view2.frame animated:YES];
+ }
+
[self setNeedsLayout];
}
View
27 GMGridView/API/GMGridViewCell.h
@@ -5,6 +5,26 @@
// Created by Gulam Moledina on 11-10-22.
// Copyright (c) 2011 GMoledina.ca. All rights reserved.
//
+// Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
#import <UIKit/UIKit.h>
@@ -13,8 +33,15 @@
@property (nonatomic, strong) UIView *contentView;
@property (nonatomic, assign, getter=isInShakingMode) BOOL inShakingMode;
+@property (nonatomic, strong) UIView *fullSizeView;
+@property (nonatomic, assign) CGSize fullSize;
+@property (nonatomic, assign, getter = isInFullSizeMode) BOOL inFullSizeMode;
+
+
- (id)initContentView:(UIView *)contentView;
- (void)shake:(BOOL)on;
+- (void)switchToFullSizeMode:(BOOL)fullSizeEnabled;
+- (void)stepToFullsizeWithAlpha:(CGFloat)alpha;
@end
View
132 GMGridView/API/GMGridViewCell.m
@@ -5,6 +5,26 @@
// Created by Gulam Moledina on 11-10-22.
// Copyright (c) 2011 GMoledina.ca. All rights reserved.
//
+// Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
#import "GMGridViewCell.h"
#import "UIView+GMGridViewShake.h"
@@ -19,6 +39,7 @@ @interface GMGridViewCell ()
}
+@property (nonatomic, assign) UIViewAutoresizing defaultFullsizeViewResizingMask;
@end
@@ -33,6 +54,10 @@ @implementation GMGridViewCell
@synthesize contentView = _contentView;
@synthesize inShakingMode = _inShakingMode;
+@synthesize fullSize = _fullSize;
+@synthesize fullSizeView = _fullSizeView;
+@synthesize inFullSizeMode = _inFullSizeMode;
+@synthesize defaultFullsizeViewResizingMask;
//////////////////////////////////////////////////////////////
#pragma mark Constructors
@@ -62,6 +87,24 @@ - (id)initContentView:(UIView *)contentView
#pragma mark
//////////////////////////////////////////////////////////////
+- (void)layoutSubviews
+{
+ if(self.inFullSizeMode)
+ {
+ CGPoint origin = CGPointMake((self.bounds.size.width - self.fullSize.width) / 2,
+ (self.bounds.size.height - self.fullSize.height) / 2);
+ self.fullSizeView.frame = CGRectMake(origin.x, origin.y, self.fullSize.width, self.fullSize.height);
+ }
+ else
+ {
+ self.fullSizeView.frame = self.bounds;
+ }
+}
+
+//////////////////////////////////////////////////////////////
+#pragma mark
+//////////////////////////////////////////////////////////////
+
- (void)setContentView:(UIView *)contentView
{
[self shake:NO];
@@ -72,6 +115,35 @@ - (void)setContentView:(UIView *)contentView
[self addSubview:_contentView];
}
+- (void)setFullSizeView:(UIView *)fullSizeView
+{
+ if ([self isInFullSizeMode])
+ {
+ fullSizeView.frame = _fullSizeView.frame;
+ fullSizeView.alpha = _fullSizeView.alpha;
+ }
+ else
+ {
+ fullSizeView.frame = self.bounds;
+ fullSizeView.alpha = 0;
+ }
+
+ self.defaultFullsizeViewResizingMask = fullSizeView.autoresizingMask | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
+
+ fullSizeView.autoresizingMask = _fullSizeView.autoresizingMask;
+
+ [_fullSizeView removeFromSuperview];
+ _fullSizeView = fullSizeView;
+ [self addSubview:_fullSizeView];
+}
+
+- (void)setFullSize:(CGSize)fullSize
+{
+ _fullSize = fullSize;
+
+ [self setNeedsLayout];
+}
+
//////////////////////////////////////////////////////////////
#pragma mark
@@ -100,4 +172,64 @@ - (void)shake:(BOOL)on
}
}
+- (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;
+
+ self.inFullSizeMode = YES;
+
+ [UIView animateWithDuration:0.1
+ animations:^{
+ self.fullSizeView.alpha = 1;
+ self.contentView.alpha = 0;
+ self.backgroundColor = [UIColor clearColor];
+ }
+ completion:^(BOOL finished){
+ [self setNeedsLayout];
+ }
+ ];
+ }
+ else
+ {
+ self.fullSizeView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+
+ self.inFullSizeMode = NO;
+
+ [UIView animateWithDuration:0.1
+ animations:^{
+ self.fullSizeView.alpha = 0;
+ self.contentView.alpha = 1;
+ self.fullSizeView.frame = self.bounds;
+ }
+ completion:^(BOOL finished){
+ [self setNeedsLayout];
+ }
+ ];
+ }
+}
+
+- (void)stepToFullsizeWithAlpha:(CGFloat)alpha
+{
+ if (![self isInFullSizeMode])
+ {
+ if (alpha > 1)
+ {
+ alpha = 1;
+ }
+ else if (alpha < 0)
+ {
+ alpha = 0;
+ }
+
+ self.fullSizeView.alpha = alpha;
+ self.contentView.alpha = 1.4 - alpha;
+ }
+}
+
@end
View
35 GMGridView/API/UIView+GMGridViewShake.h
@@ -0,0 +1,35 @@
+//
+// UIView+GMGridViewShake.h
+// GMGridView
+//
+// Created by Gulam Moledina on 11-10-22.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+// Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface UIView (GMGridViewShake)
+
+- (void)shakeStatus:(BOOL)enabled;
+
+@end
View
23 UIView+GMGridViewShake.m → GMGridView/API/UIView+GMGridViewShake.m
@@ -5,10 +5,29 @@
// Created by Gulam Moledina on 11-10-22.
// Copyright (c) 2011 GMoledina.ca. All rights reserved.
//
+// Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
-#import "UIView+GMGridViewShake.h"
#import <Quartzcore/QuartzCore.h>
-
+#import "UIView+GMGridViewShake.h"
@interface UIView (GMGridViewShake_Privates)
View
30 GMGridView/ViewController.m
@@ -79,7 +79,7 @@ - (id)init
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
- _itemSize = CGSizeMake(90, 80);
+ _itemSize = CGSizeMake(140, 110);
_itemPadding = 10;
}
else
@@ -183,6 +183,28 @@ - (UIView *)GMGridView:(GMGridView *)gridView viewForItemAtIndex:(NSInteger)inde
return view;
}
+- (CGSize)GMGridView:(GMGridView *)gridView fullSizeForView:(UIView *)view
+{
+ if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
+ {
+ return CGSizeMake(310, 310);
+ }
+ else
+ {
+ return CGSizeMake(700, 700);
+ }
+}
+
+- (UIView *)GMGridView:(GMGridView *)gridView fullSizeViewForView:(UIView *)view
+{
+ UIView *fullView = [[UIView alloc] init];
+ fullView.backgroundColor = [UIColor yellowColor];
+ fullView.layer.masksToBounds = NO;
+ fullView.layer.cornerRadius = 8;
+
+ return fullView;
+}
+
//////////////////////////////////////////////////////////////
#pragma mark DraggableGridViewSortingDelegate
@@ -241,7 +263,7 @@ - (void)GMGridView:(GMGridView *)gridView didStartTransformingView:(UIView *)vie
completion:nil];
}
-- (void)GMGridView:(GMGridView *)gridView didEndTransformingView:(UIView *)view inFullsize:(BOOL)fullSize
+- (void)GMGridView:(GMGridView *)gridView didEndTransformingView:(UIView *)view
{
[UIView animateWithDuration:0.5
delay:0
@@ -253,6 +275,10 @@ - (void)GMGridView:(GMGridView *)gridView didEndTransformingView:(UIView *)view
completion:nil];
}
+- (void)GMGridView:(GMGridView *)gridView didEnterFullSizeForView:(UIView *)view
+{
+
+}
//////////////////////////////////////////////////////////////
View
31 README
@@ -1,23 +1,30 @@
-GM-GRID-VIEW (MIT license)
---------------------------
-An iOS Grid-View allowing the user to sort the views in the scrollView.
-This view is inspired by the UITableView and uses a delegate and a datasource in order to get the data and interact with it.
+GM-GRID-VIEW
+-------------
+
+An iOS Grid-View allowing the user to sort the views in the scrollView and also to see the views in fullsize by pinching them.
+This view is inspired by the UITableView and uses a datasource and delegates in order to get the data and interact with it.
Requirements:
-- iOS 5 (for NSMutableOrderedSet and to access the UIScrollView gestureRecognizers)
+- iOS 5 (to access the UIScrollView gestureRecognizers)
- ARC
-Features:
+Features - General:
- Works on both the iPhone and iPad
- Works on both portrait and landscape orientation
+- Gestures work great inside of the scrollView
+- Demo app provided
+
+Features - Sorting:
- Perform a long-touch on a view to be able to move it
-- Works great inside a scrollView
-- Only one UIPanGestureRecognizer and one UILongTouchGestureRecognizer used to track ALL views
- Two different animation styles ("Swap" or "Push")
-- Demo app provided
+- Sorted view has a shake animation (can be disabled)
+- Only one UIPanGestureRecognizer and one UILongTouchGestureRecognizer used to track ALL views
-ToDo's:
-- Not loading all views at once (using CATiledLayer ?)
-- Adding a pinch on views to zoom them
+Features - Fullsize:
+- Pinch, rotate, drag views using 2 fingers
+- Switch to fullsize mode on the view at the end of these gestures if the view scaled enough
+- Provide a different fullsize view (detailed view) for the view via the delegate
+- Every view doesnt have it's own gesture recognizers, the main view handles a set of gestures for ALL views
+Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
View
15 UIView+GMGridViewShake.h
@@ -1,15 +0,0 @@
-//
-// UIView+GMGridViewShake.h
-// GMGridView
-//
-// Created by Gulam Moledina on 11-10-22.
-// Copyright (c) 2011 GMoledina.ca. All rights reserved.
-//
-
-#import <UIKit/UIKit.h>
-
-@interface UIView (GMGridViewShake)
-
-- (void)shakeStatus:(BOOL)enabled;
-
-@end
Please sign in to comment.
Something went wrong with that request. Please try again.