Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Full support for layout, added settings panel in demo app, set some m…

…ethods as optional in delegates, fixed minor bugs
  • Loading branch information...
commit 247d3bfa6fb355d49b6d9a83791cd7004ab58dcb 1 parent 7f81e69
@gmoledina authored
View
10 GMGridView.xcodeproj/project.pbxproj
@@ -18,13 +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 */; };
+ 169AE3781460E1B300C0CBCD /* OptionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 169AE3771460E1B300C0CBCD /* OptionsViewController.m */; };
16A0D030145342F8004D7BBC /* GMGridViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 16A0D02F145342F8004D7BBC /* GMGridViewCell.m */; };
16DF1A6E145E3456006AA43C /* GMGridViewLayoutStrategies.m in Sources */ = {isa = PBXBuildFile; fileRef = 16DF1A6D145E3456006AA43C /* GMGridViewLayoutStrategies.m */; };
16DF1A71145E3461006AA43C /* UIGestureRecognizer+GMGridViewAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 16DF1A70145E3460006AA43C /* UIGestureRecognizer+GMGridViewAdditions.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
- 16026C0C1454628800093AFF /* UIView+GMGridViewAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; name = "UIView+GMGridViewAdditions.h"; path = "GMGridView/API/UIView+GMGridViewAdditions.h"; sourceTree = SOURCE_ROOT; };
+ 16026C0C1454628800093AFF /* UIView+GMGridViewAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIView+GMGridViewAdditions.h"; path = "GMGridView/API/UIView+GMGridViewAdditions.h"; sourceTree = SOURCE_ROOT; };
16026C0D1454628800093AFF /* UIView+GMGridViewAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIView+GMGridViewAdditions.m"; path = "GMGridView/API/UIView+GMGridViewAdditions.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>"; };
@@ -42,11 +43,13 @@
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; };
+ 169AE3761460E1B300C0CBCD /* OptionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionsViewController.h; path = GMGridView/OptionsViewController.h; sourceTree = SOURCE_ROOT; };
+ 169AE3771460E1B300C0CBCD /* OptionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OptionsViewController.m; path = GMGridView/OptionsViewController.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; };
16DF1A6C145E3456006AA43C /* GMGridViewLayoutStrategies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GMGridViewLayoutStrategies.h; path = GMGridView/API/GMGridViewLayoutStrategies.h; sourceTree = SOURCE_ROOT; };
16DF1A6D145E3456006AA43C /* GMGridViewLayoutStrategies.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GMGridViewLayoutStrategies.m; path = GMGridView/API/GMGridViewLayoutStrategies.m; sourceTree = SOURCE_ROOT; };
- 16DF1A6F145E3460006AA43C /* UIGestureRecognizer+GMGridViewAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; name = "UIGestureRecognizer+GMGridViewAdditions.h"; path = "GMGridView/API/UIGestureRecognizer+GMGridViewAdditions.h"; sourceTree = SOURCE_ROOT; };
+ 16DF1A6F145E3460006AA43C /* UIGestureRecognizer+GMGridViewAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIGestureRecognizer+GMGridViewAdditions.h"; path = "GMGridView/API/UIGestureRecognizer+GMGridViewAdditions.h"; sourceTree = SOURCE_ROOT; };
16DF1A70145E3460006AA43C /* UIGestureRecognizer+GMGridViewAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIGestureRecognizer+GMGridViewAdditions.m"; path = "GMGridView/API/UIGestureRecognizer+GMGridViewAdditions.m"; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
@@ -111,6 +114,8 @@
1691D7A71442D01F00F472BF /* AppDelegate.m */,
1691D7A81442D01F00F472BF /* ViewController.h */,
1691D7A91442D01F00F472BF /* ViewController.m */,
+ 169AE3761460E1B300C0CBCD /* OptionsViewController.h */,
+ 169AE3771460E1B300C0CBCD /* OptionsViewController.m */,
16924B12144156FE00E6E556 /* Supporting Files */,
);
name = Demo;
@@ -216,6 +221,7 @@
16026C0E1454628800093AFF /* UIView+GMGridViewAdditions.m in Sources */,
16DF1A6E145E3456006AA43C /* GMGridViewLayoutStrategies.m in Sources */,
16DF1A71145E3461006AA43C /* UIGestureRecognizer+GMGridViewAdditions.m in Sources */,
+ 169AE3781460E1B300C0CBCD /* OptionsViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
40 GMGridView/API/GMGridView.h
@@ -50,12 +50,12 @@ typedef enum
}
// Delegates
-@property (nonatomic, weak) id<GMGridViewDataSource> dataSource;
-@property (nonatomic, weak) id<GMGridViewSortingDelegate> sortingDelegate;
-@property (nonatomic, weak) id<GMGridViewTransformationDelegate> transformDelegate;
+@property (nonatomic, weak) NSObject<GMGridViewDataSource> *dataSource; // Required
+@property (nonatomic, weak) NSObject<GMGridViewSortingDelegate> *sortingDelegate; // Required to enable sorting
+@property (nonatomic, weak) NSObject<GMGridViewTransformationDelegate> *transformDelegate; // Required to enable fullsize mode
// Layout Strategy
-@property (nonatomic, strong) id<GMGridViewLayoutStrategy> layoutStrategy;
+@property (nonatomic, strong) id<GMGridViewLayoutStrategy> layoutStrategy; // Default is GMGridViewLayoutVerticalStrategy
// Customizing Options
@property (nonatomic) GMGridViewStyle style; // Default is GMGridViewStyleSwap
@@ -79,21 +79,14 @@ typedef enum
#pragma mark Protocol GMGridViewDataSource
//////////////////////////////////////////////////////////////
-@protocol GMGridViewDataSource
+@protocol GMGridViewDataSource <NSObject>
+@required
// Populating subview items
- (NSInteger)numberOfItemsInGMGridView:(GMGridView *)gridView;
-- (NSInteger)widthForItemsInGMGridView:(GMGridView *)gridView;
-- (NSInteger)heightForItemsInGMGridView:(GMGridView *)gridView;
+- (CGSize)sizeForItemsInGMGridView:(GMGridView *)gridView;
- (UIView *)GMGridView:(GMGridView *)gridView viewForItemAtIndex:(NSInteger)index;
-// Item moved - right place to update the data structure
-- (void)GMGridView:(GMGridView *)gridView itemAtIndex:(NSInteger)oldIndex movedToIndex:(NSInteger)newIndex;
-
-// Fullsize
-- (CGSize)GMGridView:(GMGridView *)gridView fullSizeForView:(UIView *)view;
-- (UIView *)GMGridView:(GMGridView *)gridView fullSizeViewForView:(UIView *)view;
-
@end
@@ -101,12 +94,17 @@ typedef enum
#pragma mark Protocol GMGridViewSortingDelegate
//////////////////////////////////////////////////////////////
-@protocol GMGridViewSortingDelegate
+@protocol GMGridViewSortingDelegate <NSObject>
+@required
+// Item moved - right place to update the data structure
+- (void)GMGridView:(GMGridView *)gridView moveItemAtIndex:(NSInteger)oldIndex toIndex:(NSInteger)newIndex;
+- (void)GMGridView:(GMGridView *)gridView exchangeItemAtIndex:(NSInteger)index1 withItemAtIndex:(NSInteger)index2;
+
+@optional
// Sorting started/ended - indexes are not specified on purpose (not the right place to update data structure)
- (void)GMGridView:(GMGridView *)gridView didStartMovingView:(UIView *)view;
- (void)GMGridView:(GMGridView *)gridView didEndMovingView:(UIView *)view;
-
// Enable/Disable the shaking behavior of an item being moved
- (BOOL)GMGridView:(GMGridView *)gridView shouldAllowShakingBehaviorWhenMovingView:(UIView *)view atIndex:(NSInteger)index;
@@ -116,9 +114,15 @@ typedef enum
#pragma mark Protocol GMGridViewTransformationDelegate
//////////////////////////////////////////////////////////////
-@protocol GMGridViewTransformationDelegate
+@protocol GMGridViewTransformationDelegate <NSObject>
+
+@required
+// Fullsize
+- (CGSize)GMGridView:(GMGridView *)gridView sizeInFullSizeForView:(UIView *)view;
+- (UIView *)GMGridView:(GMGridView *)gridView fullSizeViewForView:(UIView *)view;
-// Transformation (pinch, drag, rotate) of the an item
+// Transformation (pinch, drag, rotate) of the item
+@optional
- (void)GMGridView:(GMGridView *)gridView didStartTransformingView:(UIView *)view;
- (void)GMGridView:(GMGridView *)gridView didEnterFullSizeForView:(UIView *)view;
- (void)GMGridView:(GMGridView *)gridView didEndTransformingView:(UIView *)view;
View
185 GMGridView/API/GMGridView.m
@@ -64,9 +64,11 @@ @interface GMGridView () <UIGestureRecognizerDelegate>
// Moving (sorting) control vars
GMGridViewCell *_sortMovingItem;
NSInteger _sortFuturePosition;
- CGPoint _sortMovingItemStartingPoint;
BOOL _autoScrollActive;
+ CGPoint _minPossibleContentOffset;
+ CGPoint _maxPossibleContentOffset;
+
// Transforming control vars
GMGridViewCell *_transformingItem;
CGFloat _lastRotation;
@@ -92,7 +94,6 @@ - (void)sortingMoveDidStartAtPoint:(CGPoint)point;
- (void)sortingMoveDidContinueToPoint:(CGPoint)point;
- (void)sortingMoveDidStopAtPoint:(CGPoint)point;
- (void)sortingAutoScrollMovementCheck;
-- (void)updateIndexOfItem:(UIView *)view toIndex:(NSInteger)index;
// Transformation control
- (void)transformingGestureDidBeginWithGesture:(UIGestureRecognizer *)gesture;
@@ -181,6 +182,7 @@ - (id)initWithFrame:(CGRect)frame
_sortingLongPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(sortingLongPressGestureUpdated:)];
_sortingLongPressGesture.numberOfTouchesRequired = 1;
+ _sortingLongPressGesture.delegate = self;
[_scrollView addGestureRecognizer:_sortingLongPressGesture];
@@ -189,7 +191,6 @@ - (id)initWithFrame:(CGRect)frame
[_scrollView.panGestureRecognizer requireGestureRecognizerToFail:_sortingPanGesture];
self.layoutStrategy = [GMGridViewLayoutStrategyFactory strategyFromType:GMGridViewLayoutVertical];
- //self.layoutStrategy = [GMGridViewLayoutStrategyFactory strategyFromType:GMGridViewLayoutHorizontal]; // Work in progress
self.itemSpacing = 10;
self.style = GMGridViewStyleSwap;
@@ -202,6 +203,9 @@ - (id)initWithFrame:(CGRect)frame
_lastScale = 1.0;
_lastRotation = 0.0;
+
+ _minPossibleContentOffset = CGPointMake(0, 0);
+ _maxPossibleContentOffset = CGPointMake(0, 0);
}
return self;
}
@@ -244,6 +248,12 @@ - (void)setItemSpacing:(NSInteger)itemSpacing
[self setNeedsLayout];
}
+- (void)setCenterGrid:(BOOL)centerGrid
+{
+ _centerGrid = centerGrid;
+ [self setNeedsLayout];
+}
+
- (void)setMinEdgeInsets:(UIEdgeInsets)minEdgeInsets
{
_minEdgeInsets = minEdgeInsets;
@@ -278,13 +288,17 @@ - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
CGPoint locationTouch = [_tapGesture locationInView:_scrollView];
valid = [self.layoutStrategy itemPositionFromLocation:locationTouch] != GMGV_INVALID_POSITION;
}
+ else if (gestureRecognizer == _sortingLongPressGesture)
+ {
+ valid = (self.sortingDelegate != nil);
+ }
else if (gestureRecognizer == _sortingPanGesture)
{
valid = (_sortMovingItem != nil && [_sortingLongPressGesture hasRecognizedValidGesture]);
}
else if(gestureRecognizer == _rotationGesture || gestureRecognizer == _pinchGesture || gestureRecognizer == _panGesture)
{
- if ([gestureRecognizer numberOfTouches] == 2)
+ if (self.transformDelegate != nil && [gestureRecognizer numberOfTouches] == 2)
{
CGPoint locationTouch1 = [gestureRecognizer locationOfTouch:0 inView:_scrollView];
CGPoint locationTouch2 = [gestureRecognizer locationOfTouch:1 inView:_scrollView];
@@ -355,13 +369,10 @@ - (void)sortingPanGestureUpdated:(UIPanGestureRecognizer *)panGesture
case UIGestureRecognizerStateFailed:
{
_autoScrollActive = NO;
- _sortMovingItemStartingPoint = CGPointZero;
break;
}
case UIGestureRecognizerStateBegan:
- {
- _sortMovingItemStartingPoint = [panGesture locationInView:_scrollView];
-
+ {
_autoScrollActive = YES;
[self sortingAutoScrollMovementCheck];
@@ -388,52 +399,68 @@ - (void)sortingAutoScrollMovementCheck
if (_sortMovingItem && _autoScrollActive)
{
CGPoint locationInMainView = [_sortingPanGesture locationInView:self];
- CGPoint locationInScroll = [_sortingPanGesture locationInView:_scrollView];
- CGRect visibleRect = CGRectMake(_scrollView.contentOffset.x,
- _scrollView.contentOffset.y,
- _scrollView.bounds.size.width,
- _scrollView.bounds.size.height);
+ CGPoint locationInScroll = [_sortingPanGesture locationInView:_scrollView];
+
+ CGFloat threshhold = _itemSize.height;
+ CGPoint offset = _scrollView.contentOffset;
- void (^completionBlock)(void) = ^{
- if (_autoScrollActive)
+ // Going down
+ if (locationInMainView.x + threshhold > self.bounds.size.width)
+ {
+ offset.x += _itemSize.width;
+
+ if (offset.x > _maxPossibleContentOffset.x)
{
- [self sortingMoveDidContinueToPoint:locationInScroll];
+ offset.x = _maxPossibleContentOffset.x;
}
+ }
+ // Going up
+ else if (locationInMainView.x - threshhold <= 0)
+ {
+ offset.x -= _itemSize.width;
- [self sortingAutoScrollMovementCheck];
- };
+ if (offset.x < _minPossibleContentOffset.x)
+ {
+ offset.x = _minPossibleContentOffset.x;
+ }
+ }
- if (locationInMainView.y + _itemSize.height/2 > self.bounds.size.height)
- {
- CGAffineTransform transform = CGAffineTransformTranslate(CGAffineTransformIdentity, 0, _itemSize.height);
+ // Going right
+ if (locationInMainView.y + threshhold > self.bounds.size.height)
+ {
+ offset.y += _itemSize.height;
- CGRect newVisiblerect = CGRectApplyAffineTransform(visibleRect, transform);
+ if (offset.y > _maxPossibleContentOffset.y)
+ {
+ offset.y = _maxPossibleContentOffset.y;
+ }
+ }
+ // Going leftz
+ else if (locationInMainView.y - threshhold <= 0)
+ {
+ offset.y -= _itemSize.height;
- [UIView animateWithDuration:0.2
- delay:0
- options:0
- animations:^{
- [_scrollView scrollRectToVisible:newVisiblerect animated:NO];
- }
- completion:^(BOOL finished){
- completionBlock();
- }
- ];
+ if (offset.y < _minPossibleContentOffset.y)
+ {
+ offset.y = _minPossibleContentOffset.y;
+ }
}
- else if (locationInMainView.y - _itemSize.height/2 <= 0)
+
+ if (offset.x != _scrollView.contentOffset.x || offset.y != _scrollView.contentOffset.y)
{
- CGAffineTransform transform = CGAffineTransformTranslate(CGAffineTransformIdentity, 0, -1 * _itemSize.height);
-
- CGRect newVisiblerect = CGRectApplyAffineTransform(visibleRect, transform);
-
- [UIView animateWithDuration:0.2
+ [UIView animateWithDuration:kDefaultAnimationDuration
delay:0
options:0
animations:^{
- [_scrollView scrollRectToVisible:newVisiblerect animated:NO];
+ _scrollView.contentOffset = offset;
}
completion:^(BOOL finished){
- completionBlock();
+ if (_autoScrollActive)
+ {
+ [self sortingMoveDidContinueToPoint:locationInScroll];
+ }
+
+ [self sortingAutoScrollMovementCheck];
}
];
}
@@ -463,9 +490,16 @@ - (void)sortingMoveDidStartAtPoint:(CGPoint)point
_sortFuturePosition = _sortMovingItem.tag - kTagOffset;
_sortMovingItem.tag = 0;
- [self.sortingDelegate GMGridView:self didStartMovingView:_sortMovingItem.contentView];
+ if ([self.sortingDelegate respondsToSelector:@selector(GMGridView:didStartMovingView:)])
+ {
+ [self.sortingDelegate GMGridView:self didStartMovingView:_sortMovingItem.contentView];
+ }
- if ([self.sortingDelegate GMGridView:self shouldAllowShakingBehaviorWhenMovingView:_sortMovingItem.contentView atIndex:position])
+ if ([self.sortingDelegate respondsToSelector:@selector(GMGridView:didStartMovingView:)])
+ {
+ [_sortMovingItem shake:[self.sortingDelegate GMGridView:self shouldAllowShakingBehaviorWhenMovingView:_sortMovingItem.contentView atIndex:position]];
+ }
+ else
{
[_sortMovingItem shake:YES];
}
@@ -483,18 +517,20 @@ - (void)sortingMoveDidStopAtPoint:(CGPoint)point
_sortMovingItem.frame = frameInScroll;
[_scrollView addSubview:_sortMovingItem];
- [self updateIndexOfItem:_sortMovingItem toIndex:_sortFuturePosition];
-
CGPoint newOrigin = [self.layoutStrategy originForItemAtPosition:_sortFuturePosition];
CGRect newFrame = CGRectMake(newOrigin.x, newOrigin.y, _itemSize.width, _itemSize.height);
- [UIView animateWithDuration:0.2
+ [UIView animateWithDuration:kDefaultAnimationDuration
animations:^{
_sortMovingItem.transform = CGAffineTransformIdentity;
_sortMovingItem.frame = newFrame;
}
completion:^(BOOL finished){
- [self.sortingDelegate GMGridView:self didEndMovingView:_sortMovingItem.contentView];
+ if ([self.sortingDelegate respondsToSelector:@selector(GMGridView:didEndMovingView:)])
+ {
+ [self.sortingDelegate GMGridView:self didEndMovingView:_sortMovingItem.contentView];
+ }
+
_sortMovingItem = nil;
_sortFuturePosition = GMGV_INVALID_POSITION;
}
@@ -548,6 +584,7 @@ - (void)sortingMoveDidContinueToPoint:(CGPoint)point
}
}
+ [self.sortingDelegate GMGridView:self moveItemAtIndex:_sortFuturePosition toIndex:position];
[self relayoutItems];
break;
@@ -558,6 +595,7 @@ - (void)sortingMoveDidContinueToPoint:(CGPoint)point
if (_sortMovingItem)
{
UIView *v = [self itemSubViewForPosition:position];
+
v.tag = _sortFuturePosition + kTagOffset;
CGPoint origin = [self.layoutStrategy originForItemAtPosition:_sortFuturePosition];
@@ -569,10 +607,10 @@ - (void)sortingMoveDidContinueToPoint:(CGPoint)point
}
completion:nil
];
-
- [self updateIndexOfItem:v toIndex:v.tag - kTagOffset];
}
+ [self.sortingDelegate GMGridView:self exchangeItemAtIndex:_sortFuturePosition withItemAtIndex:position];
+
break;
}
}
@@ -708,7 +746,6 @@ - (void)rotationGestureUpdated:(UIRotationGestureRecognizer *)rotationGesture
}
}
-
- (void)transformingGestureDidBeginWithGesture:(UIGestureRecognizer *)gesture
{
if (!_transformingItem)
@@ -725,13 +762,13 @@ - (void)transformingGestureDidBeginWithGesture:(UIGestureRecognizer *)gesture
[self addSubview:_transformingItem];
[self bringSubviewToFront:_transformingItem];
- if (!_transformingItem.fullSizeView)
+ _transformingItem.fullSize = [self.transformDelegate GMGridView:self sizeInFullSizeForView:_transformingItem.contentView];
+ _transformingItem.fullSizeView = [self.transformDelegate GMGridView:self fullSizeViewForView:_transformingItem];
+
+ if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didStartTransformingView:)])
{
- _transformingItem.fullSize = [self.dataSource GMGridView:self fullSizeForView:_transformingItem.contentView];
- _transformingItem.fullSizeView = [self.dataSource GMGridView:self fullSizeViewForView:_transformingItem];
+ [self.transformDelegate GMGridView:self didStartTransformingView:_transformingItem.contentView];
}
-
- [self.transformDelegate GMGridView:self didStartTransformingView:_transformingItem.contentView];
}
}
@@ -747,7 +784,6 @@ - (void)exitFullSizePinchGestureUpdated:(UIPinchGestureRecognizer *)pinchGesture
{
_inFullSizeMode = NO;
[_transformingItem removeGestureRecognizer:pinchGesture];
-
_transformingItem.frame = _transformingItem.fullSizeView.frame;
[self transformingGestureDidFinish];
@@ -796,7 +832,12 @@ - (void)transformingGestureDidFinish
completion:^(BOOL finished){
_transformingItem.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_inFullSizeMode = YES;
- [self.transformDelegate GMGridView:self didEnterFullSizeForView:_transformingItem.contentView];
+
+ if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didEnterFullSizeForView:)])
+ {
+ [self.transformDelegate GMGridView:self didEnterFullSizeForView:_transformingItem.contentView];
+ }
+
}
];
}
@@ -827,8 +868,13 @@ - (void)transformingGestureDidFinish
transformingView.frame = CGRectMake(origin.x, origin.y, _itemSize.width, _itemSize.height);
}
completion:^(BOOL finished){
+ transformingView.fullSizeView = nil;
[self relayoutItems];
- [self.transformDelegate GMGridView:self didEndTransformingView:transformingView.contentView];
+
+ if ([self.transformDelegate respondsToSelector:@selector(GMGridView:didEndTransformingView:)])
+ {
+ [self.transformDelegate GMGridView:self didEndTransformingView:transformingView.contentView];
+ }
}
];
}
@@ -956,16 +1002,6 @@ - (NSInteger)positionForItemSubview:(GMGridViewCell *)view
return position;
}
-- (void)updateIndexOfItem:(GMGridViewCell *)view toIndex:(NSInteger)index
-{
- NSUInteger oldIndex = [self positionForItemSubview:view];
-
- if (index >= 0 && oldIndex != index && oldIndex < _numberTotalItems)
- {
- [self.dataSource GMGridView:self itemAtIndex:oldIndex movedToIndex:index];
- }
-}
-
- (void)recomputeSize
{
CGRect actualBounds = CGRectMake(0,
@@ -996,6 +1032,11 @@ - (void)recomputeSize
{
_scrollView.contentInset = self.minEdgeInsets;
}
+
+ _minPossibleContentOffset = CGPointMake(-1 * (_scrollView.contentInset.left),
+ -1 * (_scrollView.contentInset.top));
+ _maxPossibleContentOffset = CGPointMake(_scrollView.contentSize.width - _scrollView.bounds.size.width + _scrollView.contentInset.right,
+ _scrollView.contentSize.height - _scrollView.bounds.size.height + _scrollView.contentInset.bottom);
}
- (void)relayoutItems
@@ -1040,11 +1081,8 @@ - (void)reloadData
[self setSubviewsCacheAsInvalid];
- NSUInteger numberItems = [self.dataSource numberOfItemsInGMGridView:self];
- NSUInteger width = [self.dataSource widthForItemsInGMGridView:self];
- NSUInteger height = [self.dataSource heightForItemsInGMGridView:self];
-
- _itemSize = CGSizeMake(width, height);
+ NSUInteger numberItems = [self.dataSource numberOfItemsInGMGridView:self];
+ _itemSize = [self.dataSource sizeForItemsInGMGridView:self];
_numberTotalItems = numberItems;
[self recomputeSize];
@@ -1056,6 +1094,7 @@ - (void)reloadData
[_scrollView addSubview:cell];
}
+ _scrollView.contentOffset = _minPossibleContentOffset;
[self setSubviewsCacheAsInvalid];
[self setNeedsLayout];
}
@@ -1127,7 +1166,7 @@ - (void)removeObjectAtIndex:(NSInteger)index
cell.tag = kTagOffset - 1;
- [UIView animateWithDuration:0.2
+ [UIView animateWithDuration:kDefaultAnimationDuration
delay:0
options:0
animations:^{
View
5 GMGridView/API/GMGridViewLayoutStrategies.h
@@ -57,6 +57,8 @@ typedef enum {
@protocol GMGridViewLayoutStrategy <NSObject>
+- (GMGridViewLayoutStrategyType)type;
+
// Setup
- (void)rebaseWithItemCount:(NSInteger)count havingSize:(CGSize)itemSize andSpacing:(NSInteger)spacing insideOfBounds:(CGRect)bounds;
@@ -76,6 +78,8 @@ typedef enum {
@interface GMGridViewLayoutStrategyBase : NSObject
{
@protected
+ // All of these vars should be set in the init method
+ GMGridViewLayoutStrategyType _type;
// All of these vars should be set in the rebase method of the child class
NSInteger _itemCount;
@@ -85,6 +89,7 @@ typedef enum {
CGSize _contentSize;
}
+@property (nonatomic, readonly) GMGridViewLayoutStrategyType type;
@property (nonatomic, readonly) NSInteger itemCount;
@property (nonatomic, readonly) CGSize itemSize;
@property (nonatomic, readonly) NSInteger itemSpacing;
View
21 GMGridView/API/GMGridViewLayoutStrategies.m
@@ -63,6 +63,7 @@ @implementation GMGridViewLayoutStrategyFactory
@implementation GMGridViewLayoutStrategyBase
+@synthesize type = _type;
@synthesize itemCount = _itemCount;
@synthesize itemSize = _itemSize;
@synthesize itemSpacing = _itemSpacing;
@@ -82,6 +83,16 @@ @implementation GMGridViewLayoutVerticalStrategy
@synthesize numberOfItemsPerRow = _numberOfItemsPerRow;
+- (id)init
+{
+ if ((self = [super init]))
+ {
+ _type = GMGridViewLayoutVertical;
+ }
+
+ return self;
+}
+
- (void)rebaseWithItemCount:(NSInteger)count havingSize:(CGSize)itemSize andSpacing:(NSInteger)spacing insideOfBounds:(CGRect)bounds
{
_itemCount = count;
@@ -158,6 +169,16 @@ @implementation GMGridViewLayoutHorizontalStrategy
@synthesize numberOfItemsPerColumn = _numberOfItemsPerColumn;
+- (id)init
+{
+ if ((self = [super init]))
+ {
+ _type = GMGridViewLayoutHorizontal;
+ }
+
+ return self;
+}
+
- (void)rebaseWithItemCount:(NSInteger)count havingSize:(CGSize)itemSize andSpacing:(NSInteger)spacing insideOfBounds:(CGRect)bounds
{
_itemCount = count;
View
17 GMGridView/OptionsViewController.h
@@ -0,0 +1,17 @@
+//
+// OptionsViewController.h
+// GMGridView
+//
+// Created by Gulam Moledina on 11-11-01.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@class GMGridView;
+
+@interface OptionsViewController : UIViewController
+
+@property (nonatomic, strong) GMGridView *gridView;
+
+@end
View
360 GMGridView/OptionsViewController.m
@@ -0,0 +1,360 @@
+//
+// OptionsViewController.m
+// GMGridView
+//
+// Created by Gulam Moledina on 11-11-01.
+// Copyright (c) 2011 GMoledina.ca. All rights reserved.
+//
+
+#import "OptionsViewController.h"
+#import "GMGridViewLayoutStrategies.h"
+#import "GMGridView.h"
+
+// Sections
+typedef enum {
+ OptionSectionLayout = 0,
+ OptionSectionSorting,
+ OptionSectionDebug,
+
+ OptionSectionsCount
+} OptionsTypeSections;
+
+// Options layout
+typedef enum {
+ OptionTypeLayoutStrategy = 0,
+ OptionsTypeLayoutSpacing,
+ OptionsTypeLayoutCenter,
+ OptionsTypeLayoutMinInsets,
+
+ OptionLayoutCount
+} OptionsTypeLayout;
+
+// Options sorting
+typedef enum {
+ OptionTypeSortingStyle = 0,
+
+ OptionSortingCount
+} OptionsTypeSorting;
+
+// Options debug
+typedef enum {
+ OptionTypeDebugGridBackground = 0,
+ OptionTypeDebugReload,
+
+ OptionDebugCount
+} OptionsTypeDebug;
+
+@interface OptionsViewController () <UITableViewDelegate, UITableViewDataSource>
+{
+ __weak UITableView *_tableView;
+}
+
+- (void)sortStyleSegmentedControlChanged:(UISegmentedControl *)control;
+- (void)layoutStrategySegmentedControlChanged:(UISegmentedControl *)control;
+- (void)layoutCenterSwitchChanged:(UISwitch *)control;
+- (void)layoutSpacingSliderChanged:(UISlider *)control;
+- (void)layoutInsetsSliderChanged:(UISlider *)control;
+- (void)debugGridBackgroundSwitchChanged:(UISwitch *)control;
+- (void)debugReloadButtonPressed:(UIButton *)control;
+
+@end
+
+//////////////////////////////////////////////////////////////
+#pragma mark - Implementation
+//////////////////////////////////////////////////////////////
+
+@implementation OptionsViewController
+
+@synthesize gridView;
+
+//////////////////////////////////////////////////////////////
+#pragma mark Constructor
+//////////////////////////////////////////////////////////////
+
+- (id)init
+{
+ if ((self = [super init]))
+ {
+ self.title = @"Options";
+ }
+ return self;
+}
+
+//////////////////////////////////////////////////////////////
+#pragma mark View lifecycle
+//////////////////////////////////////////////////////////////
+
+- (void)loadView
+{
+ UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
+ tableView.dataSource = self;
+ tableView.delegate = self;
+ self.view = tableView;
+ _tableView = tableView;
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+}
+
+- (void)viewDidUnload
+{
+ [super viewDidUnload];
+}
+
+//////////////////////////////////////////////////////////////
+#pragma mark Controller events
+//////////////////////////////////////////////////////////////
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark UITableView datasource & delegates
+//////////////////////////////////////////////////////////////
+
+- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
+{
+ return 35;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+ return OptionSectionsCount;
+}
+
+- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
+{
+ NSString *title = @"Unknown";
+
+ switch (section)
+ {
+ case OptionSectionLayout:
+ title = @"Layout";
+ break;
+ case OptionSectionSorting:
+ title = @"Sorting";
+ break;
+ case OptionSectionDebug:
+ title = @"Debug";
+ break;
+ }
+
+ return title;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ NSInteger count = 0;
+
+ switch (section)
+ {
+ case OptionSectionLayout:
+ count = OptionLayoutCount;
+ break;
+ case OptionSectionSorting:
+ count = OptionSortingCount;
+ break;
+ case OptionSectionDebug:
+ count = OptionDebugCount;
+ break;
+ }
+
+ return count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ static NSString *cellIdentifier = @"cell";
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
+
+ if (!cell)
+ {
+ cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
+ cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ }
+
+ if ([indexPath section] == OptionSectionLayout)
+ {
+ switch ([indexPath row])
+ {
+ case OptionTypeLayoutStrategy:
+ {
+ cell.detailTextLabel.text = @"Strategy";
+
+ UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Vertical", @"Horizontal", nil]];
+ segmentedControl.frame = CGRectMake(0, 0, 200, 30);
+ [segmentedControl addTarget:self action:@selector(layoutStrategySegmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
+ segmentedControl.selectedSegmentIndex = [self.gridView.layoutStrategy type] == GMGridViewLayoutVertical ? 0 : 1;
+
+ cell.accessoryView = segmentedControl;
+ break;
+ }
+ case OptionsTypeLayoutCenter:
+ {
+ cell.detailTextLabel.text = @"Center";
+
+ UISwitch *centerSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
+ [centerSwitch addTarget:self action:@selector(layoutCenterSwitchChanged:) forControlEvents:UIControlEventValueChanged];
+ centerSwitch.on = self.gridView.centerGrid;
+
+ cell.accessoryView = centerSwitch;
+
+ break;
+ }
+ case OptionsTypeLayoutSpacing:
+ {
+ cell.detailTextLabel.text = @"Spacing";
+
+ UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
+ [slider setMinimumValue:0];
+ [slider setMaximumValue:20];
+ [slider setValue:self.gridView.itemSpacing];
+ [slider setContinuous:NO];
+ [slider addTarget:self action:@selector(layoutSpacingSliderChanged:) forControlEvents:UIControlEventValueChanged];
+
+ cell.accessoryView = slider;
+
+ break;
+ }
+ case OptionsTypeLayoutMinInsets:
+ {
+ cell.detailTextLabel.text = @"Edge insets";
+
+ UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
+ [slider setMinimumValue:0];
+ [slider setMaximumValue:50];
+ [slider setValue:self.gridView.minEdgeInsets.top];
+ [slider setContinuous:NO];
+ [slider addTarget:self action:@selector(layoutInsetsSliderChanged:) forControlEvents:UIControlEventValueChanged];
+
+ cell.accessoryView = slider;
+ break;
+ }
+ }
+ }
+ else if ([indexPath section] == OptionSectionSorting)
+ {
+ switch ([indexPath row])
+ {
+ case OptionTypeSortingStyle:
+ {
+ cell.detailTextLabel.text = @"Style";
+
+ UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Swap", @"Push", nil]];
+ segmentedControl.frame = CGRectMake(0, 0, 150, 30);
+ [segmentedControl addTarget:self action:@selector(sortStyleSegmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
+ segmentedControl.selectedSegmentIndex = (self.gridView.style == GMGridViewStylePush) ? 1 : 0;
+
+ cell.accessoryView = segmentedControl;
+
+ break;
+ }
+ }
+ }
+ else if ([indexPath section] == OptionSectionDebug)
+ {
+ switch ([indexPath row])
+ {
+ case OptionTypeDebugGridBackground:
+ {
+ cell.detailTextLabel.text = @"Grid background color";
+
+ UISwitch *backgroundSwitch = [[UISwitch alloc] init];
+ [backgroundSwitch addTarget:self action:@selector(debugGridBackgroundSwitchChanged:) forControlEvents:UIControlEventValueChanged];
+ backgroundSwitch.on = (self.gridView.backgroundColor != [UIColor clearColor]);
+ [backgroundSwitch sizeToFit];
+
+ cell.accessoryView = backgroundSwitch;
+
+ break;
+ }
+ case OptionTypeDebugReload:
+ {
+ cell.detailTextLabel.text = @"Reload from Datasource";
+
+ UIButton *reloadButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
+ [reloadButton setReversesTitleShadowWhenHighlighted:YES];
+ [reloadButton setTitleColor:[UIColor redColor] forState:UIControlEventTouchUpInside];
+ [reloadButton setTitle:@"Reload" forState:UIControlStateNormal];
+ [reloadButton addTarget:self action:@selector(debugReloadButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
+ [reloadButton sizeToFit];
+
+ cell.accessoryView = reloadButton;
+
+ break;
+ }
+ }
+ }
+
+ return cell;
+}
+
+- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ return NO;
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark Control callbacks
+//////////////////////////////////////////////////////////////
+
+- (void)sortStyleSegmentedControlChanged:(UISegmentedControl *)control
+{
+ switch (control.selectedSegmentIndex)
+ {
+ case 1:
+ self.gridView.style = GMGridViewStylePush;
+ break;
+ case 0:
+ default:
+ self.gridView.style = GMGridViewStyleSwap;
+ break;
+ }
+}
+
+- (void)layoutStrategySegmentedControlChanged:(UISegmentedControl *)control
+{
+ switch (control.selectedSegmentIndex)
+ {
+ case 1:
+ self.gridView.layoutStrategy = [GMGridViewLayoutStrategyFactory strategyFromType:GMGridViewLayoutHorizontal];
+ break;
+ case 0:
+ default:
+ self.gridView.layoutStrategy = [GMGridViewLayoutStrategyFactory strategyFromType:GMGridViewLayoutVertical];
+ break;
+ }
+}
+
+- (void)layoutCenterSwitchChanged:(UISwitch *)control
+{
+ self.gridView.centerGrid = control.on;
+}
+
+- (void)layoutSpacingSliderChanged:(UISlider *)control
+{
+ self.gridView.itemSpacing = control.value;
+}
+
+- (void)layoutInsetsSliderChanged:(UISlider *)control
+{
+ self.gridView.minEdgeInsets = UIEdgeInsetsMake(control.value, control.value, control.value, control.value);
+}
+
+- (void)debugGridBackgroundSwitchChanged:(UISwitch *)control
+{
+ self.gridView.backgroundColor = control.on ? [UIColor lightGrayColor] : [UIColor clearColor];
+}
+
+- (void)debugReloadButtonPressed:(UIButton *)control
+{
+ [self.gridView reloadData];
+}
+
+@end
View
235 GMGridView/ViewController.m
@@ -6,11 +6,14 @@
// Copyright (c) 2011 GMoledina.ca. All rights reserved.
//
+#import <QuartzCore/QuartzCore.h>
#import "ViewController.h"
#import "GMGridView.h"
-#import <QuartzCore/QuartzCore.h>
+#import "OptionsViewController.h"
#define NUMBER_ITEMS_ON_LOAD 250
+#define INTERFACE_IS_PAD ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
+#define INTERFACE_IS_PHONE ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
//////////////////////////////////////////////////////////////
#pragma mark -
@@ -20,16 +23,18 @@
@interface ViewController () <GMGridViewDataSource, GMGridViewSortingDelegate, GMGridViewTransformationDelegate>
{
__weak GMGridView *_gmGridView;
+ UINavigationController *_optionsNav;
+ UIPopoverController *_optionsPopOver;
+
NSMutableArray *_data;
- CGSize _itemSize;
- CGFloat _itemPadding;
}
- (void)addMoreItem;
- (void)removeItem;
- (void)refreshItem;
-- (void)segmentedControlChanged:(UISegmentedControl *)control;
- (void)presentInfo;
+- (void)presentOptions:(UIBarButtonItem *)barButton;
+- (void)optionsDoneAction;
@end
@@ -46,6 +51,8 @@ - (id)init
{
if ((self =[super init]))
{
+ self.title = @"GM-GridView";
+
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addMoreItem)];
UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
@@ -57,17 +64,13 @@ - (id)init
space2.width = 10;
UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshItem)];
-
- UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Swap", @"Push", nil]];
- segmentedControl.frame = CGRectMake(0, 0, 150, 30);
- [segmentedControl addTarget:self action:@selector(segmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
- segmentedControl.selectedSegmentIndex = 0;
- UIBarButtonItem *segmentedBarItem = [[UIBarButtonItem alloc] initWithCustomView:segmentedControl];
+ self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:addButton, space, removeButton, space2, refreshButton, nil];
- self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:addButton, space, removeButton, space2, refreshButton, nil];
- self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:segmentedBarItem, nil];
+ UIBarButtonItem *optionsButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(presentOptions:)];
+
+ self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:optionsButton, nil];
_data = [[NSMutableArray alloc] init];
@@ -77,16 +80,6 @@ - (id)init
[_data addObject:[NSString stringWithFormat:@"%d", i]];
}
- if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
- {
- _itemSize = CGSizeMake(140, 110);
- _itemPadding = 10;
- }
- else
- {
- _itemSize = CGSizeMake(230, 175);
- _itemPadding = 15;
- }
}
return self;
@@ -99,20 +92,24 @@ - (id)init
- (void)loadView
{
[super loadView];
+ self.view.backgroundColor = [UIColor whiteColor];
+
+ NSInteger spacing = INTERFACE_IS_PHONE ? 10 : 15;
GMGridView *gmGridView = [[GMGridView alloc] initWithFrame:self.view.bounds];
- gmGridView.style = GMGridViewStyleSwap;
gmGridView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- gmGridView.itemSpacing = _itemPadding;
- gmGridView.centerGrid = YES;
- gmGridView.backgroundColor = [UIColor whiteColor];
+ gmGridView.backgroundColor = [UIColor clearColor];
[self.view addSubview:gmGridView];
_gmGridView = gmGridView;
- _gmGridView.sortingDelegate = self;
+ _gmGridView.style = GMGridViewStyleSwap;
+ _gmGridView.itemSpacing = spacing;
+ _gmGridView.minEdgeInsets = UIEdgeInsetsMake(spacing, spacing, spacing, spacing);
+ _gmGridView.centerGrid = YES;
+ _gmGridView.sortingDelegate = self;
_gmGridView.transformDelegate = self;
_gmGridView.dataSource = self;
-
+
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
infoButton.frame = CGRectMake(self.view.bounds.size.width - 40,
self.view.bounds.size.height - 40,
@@ -121,6 +118,19 @@ - (void)loadView
infoButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
[infoButton addTarget:self action:@selector(presentInfo) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:infoButton];
+
+
+ OptionsViewController *optionsController = [[OptionsViewController alloc] init];
+ optionsController.gridView = gmGridView;
+ optionsController.contentSizeForViewInPopover = CGSizeMake(400, 500);
+
+ _optionsNav = [[UINavigationController alloc] initWithRootViewController:optionsController];
+
+ if (INTERFACE_IS_PHONE)
+ {
+ UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(optionsDoneAction)];
+ optionsController.navigationItem.rightBarButtonItem = doneButton;
+ }
}
@@ -143,7 +153,7 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface
//////////////////////////////////////////////////////////////
-#pragma mark DraggableGridViewDataSource
+#pragma mark GMGridViewDataSource
//////////////////////////////////////////////////////////////
- (NSInteger)numberOfItemsInGMGridView:(GMGridView *)gridView
@@ -151,19 +161,23 @@ - (NSInteger)numberOfItemsInGMGridView:(GMGridView *)gridView
return [_data count];
}
-- (NSInteger)widthForItemsInGMGridView:(GMGridView *)gridView
+- (CGSize)sizeForItemsInGMGridView:(GMGridView *)gridView
{
- return _itemSize.width;
-}
-
-- (NSInteger)heightForItemsInGMGridView:(GMGridView *)gridView
-{
- return _itemSize.height;
+ if (INTERFACE_IS_PHONE)
+ {
+ return CGSizeMake(140, 110);
+ }
+ else
+ {
+ return CGSizeMake(230, 175);
+ }
}
- (UIView *)GMGridView:(GMGridView *)gridView viewForItemAtIndex:(NSInteger)index
{
- UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _itemSize.width, _itemSize.height)];
+ CGSize size = [self sizeForItemsInGMGridView:gridView];
+
+ UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
view.backgroundColor = [UIColor redColor];
view.layer.masksToBounds = NO;
view.layer.cornerRadius = 8;
@@ -183,9 +197,62 @@ - (UIView *)GMGridView:(GMGridView *)gridView viewForItemAtIndex:(NSInteger)inde
return view;
}
-- (CGSize)GMGridView:(GMGridView *)gridView fullSizeForView:(UIView *)view
+
+//////////////////////////////////////////////////////////////
+#pragma mark GMGridViewSortingDelegate
+//////////////////////////////////////////////////////////////
+
+- (void)GMGridView:(GMGridView *)gridView didStartMovingView:(UIView *)view
+{
+ [UIView animateWithDuration:0.3
+ delay:0
+ options:UIViewAnimationOptionAllowUserInteraction
+ animations:^{
+ view.backgroundColor = [UIColor orangeColor];
+ view.layer.shadowOpacity = 0.7;
+ }
+ completion:nil
+ ];
+}
+
+- (void)GMGridView:(GMGridView *)gridView didEndMovingView:(UIView *)view
+{
+ [UIView animateWithDuration:0.3
+ delay:0
+ options:UIViewAnimationOptionAllowUserInteraction
+ animations:^{
+ view.backgroundColor = [UIColor redColor];
+ view.layer.shadowOpacity = 0;
+ }
+ completion:nil
+ ];
+}
+
+- (BOOL)GMGridView:(GMGridView *)gridView shouldAllowShakingBehaviorWhenMovingView:(UIView *)view atIndex:(NSInteger)index
+{
+ return YES;
+}
+
+- (void)GMGridView:(GMGridView *)gridView moveItemAtIndex:(NSInteger)oldIndex toIndex:(NSInteger)newIndex
+{
+ NSObject *object = [_data objectAtIndex:oldIndex];
+ [_data removeObject:object];
+ [_data insertObject:object atIndex:newIndex];
+}
+
+- (void)GMGridView:(GMGridView *)gridView exchangeItemAtIndex:(NSInteger)index1 withItemAtIndex:(NSInteger)index2
{
- if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
+ [_data exchangeObjectAtIndex:index1 withObjectAtIndex:index2];
+}
+
+
+//////////////////////////////////////////////////////////////
+#pragma mark DraggableGridViewTransformingDelegate
+//////////////////////////////////////////////////////////////
+
+- (CGSize)GMGridView:(GMGridView *)gridView sizeInFullSizeForView:(UIView *)view
+{
+ if (INTERFACE_IS_PHONE)
{
return CGSizeMake(310, 310);
}
@@ -202,7 +269,7 @@ - (UIView *)GMGridView:(GMGridView *)gridView fullSizeViewForView:(UIView *)view
fullView.layer.masksToBounds = NO;
fullView.layer.cornerRadius = 8;
- CGSize size = [self GMGridView:gridView fullSizeForView:view];
+ CGSize size = [self GMGridView:gridView sizeInFullSizeForView:view];
fullView.bounds = CGRectMake(0, 0, size.width, size.height);
UILabel *label = [[UILabel alloc] initWithFrame:fullView.bounds];
@@ -211,7 +278,7 @@ - (UIView *)GMGridView:(GMGridView *)gridView fullSizeViewForView:(UIView *)view
label.backgroundColor = [UIColor clearColor];
label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
+ if (INTERFACE_IS_PHONE)
{
label.font = [UIFont boldSystemFontOfSize:15];
}
@@ -226,52 +293,6 @@ - (UIView *)GMGridView:(GMGridView *)gridView fullSizeViewForView:(UIView *)view
return fullView;
}
-
-//////////////////////////////////////////////////////////////
-#pragma mark DraggableGridViewSortingDelegate
-//////////////////////////////////////////////////////////////
-
-- (BOOL)GMGridView:(GMGridView *)gridView shouldAllowShakingBehaviorWhenMovingView:(UIView *)view atIndex:(NSInteger)index
-{
- return YES;
-}
-
-- (void)GMGridView:(GMGridView *)gridView itemAtIndex:(NSInteger)oldIndex movedToIndex:(NSInteger)newIndex
-{
- [_data exchangeObjectAtIndex:oldIndex withObjectAtIndex:newIndex];
-}
-
-- (void)GMGridView:(GMGridView *)gridView didStartMovingView:(UIView *)view
-{
- [UIView animateWithDuration:0.3
- delay:0
- options:UIViewAnimationOptionAllowUserInteraction
- animations:^{
- view.backgroundColor = [UIColor orangeColor];
- view.layer.shadowOpacity = 0.7;
- }
- completion:nil
- ];
-}
-
-- (void)GMGridView:(GMGridView *)gridView didEndMovingView:(UIView *)view
-{
- [UIView animateWithDuration:0.3
- delay:0
- options:UIViewAnimationOptionAllowUserInteraction
- animations:^{
- view.backgroundColor = [UIColor redColor];
- view.layer.shadowOpacity = 0;
- }
- completion:nil
- ];
-}
-
-
-//////////////////////////////////////////////////////////////
-#pragma mark DraggableGridViewTransformingDelegate
-//////////////////////////////////////////////////////////////
-
- (void)GMGridView:(GMGridView *)gridView didStartTransformingView:(UIView *)view
{
[UIView animateWithDuration:0.5
@@ -353,17 +374,39 @@ - (void)presentInfo
[alertView show];
}
-- (void)segmentedControlChanged:(UISegmentedControl *)control
+- (void)presentOptions:(UIBarButtonItem *)barButton
{
- switch (control.selectedSegmentIndex)
+ if (INTERFACE_IS_PHONE)
+ {
+ [self presentModalViewController:_optionsNav animated:YES];
+ }
+ else
+ {
+ if(![_optionsPopOver isPopoverVisible])
+ {
+ if (!_optionsPopOver)
+ {
+ _optionsPopOver = [[UIPopoverController alloc] initWithContentViewController:_optionsNav];
+ }
+
+ [_optionsPopOver presentPopoverFromBarButtonItem:barButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
+ }
+ else
+ {
+ [self optionsDoneAction];
+ }
+ }
+}
+
+- (void)optionsDoneAction
+{
+ if (INTERFACE_IS_PHONE)
+ {
+ [self dismissModalViewControllerAnimated:YES];
+ }
+ else
{
- case 1:
- _gmGridView.style = GMGridViewStylePush;
- break;
- case 0:
- default:
- _gmGridView.style = GMGridViewStyleSwap;
- break;
+ [_optionsPopOver dismissPopoverAnimated:YES];
}
}
View
8 README
@@ -10,10 +10,12 @@ Requirements:
- Frameworks: Foundation, UIKit, CoreGraphics and QuartzCore
Features - General:
-- Works on both the iPhone and iPad
+- Works on both the iPhone and iPad (best suited for iPad)
- Works on both portrait and landscape orientation
- Gestures work great inside of the scrollView
-- Demo app provided
+- Different layout strategies (Vertical and Horizontal)
+- Possibility to provide your own layout strategy
+- Demo app provided, with options panel
Features - Sorting:
- Perform a long-touch on a view to be able to move it
@@ -28,8 +30,8 @@ Features - Fullsize:
- Every view doesnt have it's own gesture recognizers, the main view handles a set of gestures for ALL views
COMING SOON :
-- Different layouting strategies !
- More demo content
- Changing the zoom scale dynamically (when pinching to go fullscreen)
+- Delegate callbacks for tap and double-tap
Latest code can be found on GitHub: https://github.com/gmoledina/GMGridView
Please sign in to comment.
Something went wrong with that request. Please try again.