From 096f1d7c39cc17920675032765bf262d96d8410a Mon Sep 17 00:00:00 2001 From: Artur Wdowiarski Date: Fri, 4 Jan 2013 14:08:40 +0100 Subject: [PATCH 1/8] Fixes #7. Last cells in rows not showing again after they are pulled off when the quilt view bounces. --- TMQuiltView/TMQuiltView/TMQuiltView.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.m b/TMQuiltView/TMQuiltView/TMQuiltView.m index abad306..95422f9 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.m +++ b/TMQuiltView/TMQuiltView/TMQuiltView.m @@ -466,6 +466,10 @@ - (void)layoutSubviews { // Harvest any any views that have moved off screen and add them to the reuse pool for (NSIndexPath* indexPath in [indexPathToView allKeys]) { TMQuiltViewCell *view = [indexPathToView objectForKey:indexPath]; + // Do not harvest the last cell in the column + if (*bottom == [indexPaths count] - 1) { + continue; + } if (![TMQuiltView isRect:view.frame partiallyInScrollView:self]) { // Rect intersection? [indexPathToView removeObjectForKey:indexPath]; // Limit the size on the reuse pool From 2cd1a3eaa6ad4b149dd5b4c69513dd254cf76dca Mon Sep 17 00:00:00 2001 From: Artur Wdowiarski Date: Fri, 4 Jan 2013 22:54:35 +0100 Subject: [PATCH 2/8] Fixes #7. It turned out that the previous fix was quite stupid. --- TMQuiltView/TMQuiltView/TMQuiltView.m | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.m b/TMQuiltView/TMQuiltView/TMQuiltView.m index 95422f9..7389d09 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.m +++ b/TMQuiltView/TMQuiltView/TMQuiltView.m @@ -449,8 +449,7 @@ - (void)layoutSubviews { } (*bottom)++; } - - + // Add a new cell to the top if our top cell is below the top of the visible area (and not the first cell) while ((*top > 0) && [TMQuiltView isRect:[self rectForCellAtIndex:*top column:i] entirelyInOrBelowScrollView:self]) { if ([TMQuiltView isRect:[self rectForCellAtIndex:*top - 1 column:i] partiallyInScrollView:self]) { @@ -466,12 +465,10 @@ - (void)layoutSubviews { // Harvest any any views that have moved off screen and add them to the reuse pool for (NSIndexPath* indexPath in [indexPathToView allKeys]) { TMQuiltViewCell *view = [indexPathToView objectForKey:indexPath]; - // Do not harvest the last cell in the column - if (*bottom == [indexPaths count] - 1) { - continue; - } + if (![TMQuiltView isRect:view.frame partiallyInScrollView:self]) { // Rect intersection? [indexPathToView removeObjectForKey:indexPath]; + // Limit the size on the reuse pool if ([[self reusableViewsWithReuseIdentifier:view.reuseIdentifier] count] < 10) { [[self reusableViewsWithReuseIdentifier:view.reuseIdentifier] addObject:view]; @@ -497,6 +494,19 @@ - (void)layoutSubviews { break; } } + + // The last cell in a column might have been harvested after our scroll view bounce. + // Here we check if the last cell's frame is partially in our scroll view + if (*bottom == [indexPaths count] - 1 && [TMQuiltView isRect:[self rectForCellAtIndex:*bottom column:i] partiallyInScrollView:self]){ + NSIndexPath *indexPath = [indexPaths objectAtIndex:*bottom]; + // We check, if the last cell has actually been harvested... + if ([indexPathToView objectForKey:indexPath] == nil) { + // ... and if so, we add it back + UIView* cell = [self.dataSource quiltView:self cellAtIndexPath:indexPath]; + [self addSubview:cell]; + [indexPathToView setObject:cell forKey:indexPath]; + } + } } } From 9e4a9377ae3aeecf30576f399aaba7174f9cd306 Mon Sep 17 00:00:00 2001 From: Artur Wdowiarski Date: Wed, 9 Jan 2013 21:03:11 +0100 Subject: [PATCH 3/8] Make it possible to place tappable UIControl elements in cells for iOS < 6. --- TMQuiltView/TMQuiltView/TMQuiltView.h | 2 +- TMQuiltView/TMQuiltView/TMQuiltView.m | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.h b/TMQuiltView/TMQuiltView/TMQuiltView.h index a6a5537..edce12f 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.h +++ b/TMQuiltView/TMQuiltView/TMQuiltView.h @@ -55,7 +55,7 @@ typedef enum { @end -@interface TMQuiltView : UIScrollView +@interface TMQuiltView : UIScrollView @property (nonatomic, assign) id dataSource; @property (nonatomic, assign) id delegate; diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.m b/TMQuiltView/TMQuiltView/TMQuiltView.m index 7389d09..e73d4be 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.m +++ b/TMQuiltView/TMQuiltView/TMQuiltView.m @@ -562,6 +562,7 @@ + (BOOL)isRect:(CGRect)rect partiallyInScrollView:(UIScrollView *)scrollView { - (UITapGestureRecognizer *)tapGestureRecognizer { if (!_tapGestureRecognizer) { _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewTapped:)]; + _tapGestureRecognizer.delegate = self; } return _tapGestureRecognizer; } @@ -591,6 +592,13 @@ - (void)viewTapped:(UIGestureRecognizer *)recognizer { } +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { + if ([touch.view isKindOfClass:[UIControl class]]) { + // we touched a button, slider, or other UIControl + return NO; // ignore the touch + } + return YES; // handle the touch +} @end From a1acfbcdbc4463e62a1b279614bc3361ad3026de Mon Sep 17 00:00:00 2001 From: Artur Wdowiarski Date: Thu, 10 Jan 2013 18:59:06 +0100 Subject: [PATCH 4/8] Make it possible to place an MPMoviePlayer in the QuiltView and have it behaving correctly when it exits from fullscreen in iOS 6. The problem in this case was that as of iOS6 viewWillAppear is called on the controller presenting an MPMoviePlayer when the player exits fullscreen. As a result setFrame is called on the controller's view, which in our case led to the resetView being called, which in turn threw away all the cells, including the one with the MPMoviePlayer and this (finally!) caused the player to be minimalized to the outside of the controller's view. phew! --- TMQuiltView/TMQuiltView/TMQuiltView.m | 31 ++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.m b/TMQuiltView/TMQuiltView/TMQuiltView.m index e73d4be..8af2f50 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.m +++ b/TMQuiltView/TMQuiltView/TMQuiltView.m @@ -26,7 +26,9 @@ NSString *const kDefaultReusableIdentifier = @"kTMQuiltViewDefaultReusableIdentifier"; -@interface TMQuiltView() +@interface TMQuiltView(){ + BOOL _videoPlayedInFullScreen; +} @property (nonatomic, readonly, retain) NSMutableSet *indexPaths; @property (nonatomic, readonly, retain) NSMutableDictionary *reusableViewsDictionary; @@ -126,9 +128,24 @@ - (id)initWithFrame:(CGRect)frame super.alwaysBounceVertical = YES; [self addGestureRecognizer:self.tapGestureRecognizer]; _numberOfColumms = kTMQuiltViewDefaultColumns; + _videoPlayedInFullScreen = NO; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoInFullScreenDidStart:) name:@"UIMoviePlayerControllerDidEnterFullscreenNotification" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(videoInFullScreenDidEnd:) name:@"UIMoviePlayerControllerDidExitFullscreenNotification" object:nil]; + } return self; } + +- (void)videoInFullScreenDidStart:(id)notification +{ + _videoPlayedInFullScreen = YES; +} + +- (void)videoInFullScreenDidEnd:(id)notification +{ + _videoPlayedInFullScreen = NO; +} + - (void)setDelegate:(id)delegate { [super setDelegate:delegate]; @@ -397,7 +414,7 @@ - (CGRect)rectForCellAtIndex:(int)index column:(int)column { [self cellWidth], height); } -- (void)layoutSubviews { +- (void)layoutSubviews { [super layoutSubviews]; self.contentSize = CGSizeMake(self.bounds.size.width, self.contentSize.height); @@ -511,9 +528,17 @@ - (void)layoutSubviews { } - (void)setFrame:(CGRect)frame { + // If we have an MPMoviePlayer that is just exiting fullscreen, + // removing it's superview from the view hierarchy would cause + // the minimalize animation to be broken + if (_videoPlayedInFullScreen) { + _videoPlayedInFullScreen = NO; + return; + } + [super setFrame:frame]; - // We need to recompute the cell tops because their width is + // We need to recompute the cell tops because their width is // based on the bounding width, and their height is generally based // on their width. [self resetView]; From 5f48c8e6c23f0b9b0b8fe60c19f6221925673ce9 Mon Sep 17 00:00:00 2001 From: zangcw Date: Sat, 13 Jul 2013 00:38:16 +0800 Subject: [PATCH 5/8] init with coder.for storyboard or xib --- TMQuiltView/TMQuiltView/TMQuiltView.m | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.m b/TMQuiltView/TMQuiltView/TMQuiltView.m index abad306..95ec27d 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.m +++ b/TMQuiltView/TMQuiltView/TMQuiltView.m @@ -130,6 +130,18 @@ - (id)initWithFrame:(CGRect)frame return self; } +- (id)initWithCoder:(NSCoder *)aDecoder +{ + self = [super initWithCoder:aDecoder]; + if (self) { + super.alwaysBounceVertical = YES; + [self addGestureRecognizer:self.tapGestureRecognizer]; + _numberOfColumms = kTMQuiltViewDefaultColumns; + } + return self; +} + + - (void)setDelegate:(id)delegate { [super setDelegate:delegate]; } From 5601dc0881e6f5d14c268915a8b80bfdb5170715 Mon Sep 17 00:00:00 2001 From: zangcw Date: Sat, 13 Jul 2013 00:42:57 +0800 Subject: [PATCH 6/8] add pod spec for cocoa pods --- TMQuiltView.podspec | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 TMQuiltView.podspec diff --git a/TMQuiltView.podspec b/TMQuiltView.podspec new file mode 100644 index 0000000..6e511b6 --- /dev/null +++ b/TMQuiltView.podspec @@ -0,0 +1,24 @@ +Pod::Spec.new do |s| + s.name = "TMQuiltView" + s.version = "0.0.1" + s.summary = "Interface similar to the UITableView with UI similar to Pintrest." + s.homepage = "https://github.com/1000Memories/TMQuiltView" + s.license = { + :type => 'MIT', + :text => <<-LICENSE + Copyright (c) 2012 1000memories + + 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. + +LICENSE + } + s.author = { "1000Memories" => "developers@1000memories.com" } + s.source = { :git => "https://github.com/1000Memories/TMQuiltView.git", :commit => "99a0f20259b12695c5c233e3921f88061d450b75" } + s.platform = :ios + + s.source_files = 'TMQuiltView/TMQuiltView/*.{h,m}' +end From ebe060aebe8898c37fa1f1888291f01bcd9e7f8e Mon Sep 17 00:00:00 2001 From: zangcw Date: Sat, 13 Jul 2013 01:13:54 +0800 Subject: [PATCH 7/8] add header in quilt view --- TMQuiltView/TMQuiltView/TMQuiltView.h | 3 +- TMQuiltView/TMQuiltView/TMQuiltView.m | 32 +++++++++++++++++-- .../TMDemoQuiltViewController.m | 5 +++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.h b/TMQuiltView/TMQuiltView/TMQuiltView.h index a6a5537..7f3dbf4 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.h +++ b/TMQuiltView/TMQuiltView/TMQuiltView.h @@ -59,7 +59,7 @@ typedef enum { @property (nonatomic, assign) id dataSource; @property (nonatomic, assign) id delegate; - +@property(nonatomic,retain) UIView *quiltHeaderView; // Returns the cell if it's visible and indexPath is valid. Returns nil otherwise - (TMQuiltViewCell *)cellAtIndexPath:(NSIndexPath*)indexPath; @@ -72,7 +72,6 @@ typedef enum { // Reloads all the cells. You need to call this if the number of columns changes. - (void)reloadData; - // Currently calling beginUpdates and endUpdates before and after row insertions and removals is required. - (void)beginUpdates; - (void)endUpdates; diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.m b/TMQuiltView/TMQuiltView/TMQuiltView.m index 95ec27d..f6dd8a4 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.m +++ b/TMQuiltView/TMQuiltView/TMQuiltView.m @@ -72,7 +72,7 @@ @implementation TMQuiltView @synthesize rowsToInsert = _rowsToInsert; @synthesize tapGestureRecognizer = _tapGestureRecognizer; - +@synthesize quiltHeaderView = _quiltHeaderView; #pragma mark - Memory Management - (void)dealloc { @@ -134,6 +134,15 @@ - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { + if (self.subviews.count > 1) { + assert(false); //don't use too many views in quiltview, just only one can use to header + } + if (self.subviews.count == 1) { + _quiltHeaderView = [[self.subviews objectAtIndex:0] retain]; + CGRect headerFrame = self.quiltHeaderView.frame; + headerFrame.origin.y = 0; + self.quiltHeaderView.frame = headerFrame; + } super.alwaysBounceVertical = YES; [self addGestureRecognizer:self.tapGestureRecognizer]; _numberOfColumms = kTMQuiltViewDefaultColumns; @@ -141,6 +150,21 @@ - (id)initWithCoder:(NSCoder *)aDecoder return self; } +- (void)setQuiltHeaderView:(UIView *)quiltHeaderView +{ + [self willChangeValueForKey:@"quiltHeaderView"]; + [quiltHeaderView removeFromSuperview]; + [quiltHeaderView retain]; + [_quiltHeaderView removeFromSuperview]; + [_quiltHeaderView release]; + _quiltHeaderView = quiltHeaderView; + + CGRect headerFrame = _quiltHeaderView.frame; + headerFrame.origin.y = 0; + _quiltHeaderView.frame = headerFrame; + [self addSubview:_quiltHeaderView]; + [self didChangeValueForKey:@"quiltHeaderView"]; +} - (void)setDelegate:(id)delegate { [super setDelegate:delegate]; @@ -327,7 +351,11 @@ - (void)resetView { float heights[_numberOfColumms]; for (int i = 0; i < _numberOfColumms; i++) { - heights[i] = 0.0; + if (self.quiltHeaderView) { + heights[i] = self.quiltHeaderView.frame.size.height; + } else { + heights[i] = 0.0; + } } for (int i = 0; i < _numberOfColumms; i++) { diff --git a/TMQuiltViewDemo/TMQuiltViewDemo/TMDemoQuiltViewController.m b/TMQuiltViewDemo/TMQuiltViewDemo/TMDemoQuiltViewController.m index 7bd6b50..adf62f1 100644 --- a/TMQuiltViewDemo/TMQuiltViewDemo/TMDemoQuiltViewController.m +++ b/TMQuiltViewDemo/TMQuiltViewDemo/TMDemoQuiltViewController.m @@ -46,6 +46,11 @@ - (void)viewDidLoad [super viewDidLoad]; self.quiltView.backgroundColor = [UIColor blackColor]; + UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 150)]; + header.backgroundColor = [UIColor blueColor]; + self.quiltView.quiltHeaderView = header; + [header release]; + } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation From 0b3caba016529d77204e8cc0d2cb46b4cd25f17b Mon Sep 17 00:00:00 2001 From: zangcw Date: Sat, 13 Jul 2013 01:36:11 +0800 Subject: [PATCH 8/8] remove initWithCoder add header view.use IBOutlet --- TMQuiltView/TMQuiltView/TMQuiltView.h | 2 +- TMQuiltView/TMQuiltView/TMQuiltView.m | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.h b/TMQuiltView/TMQuiltView/TMQuiltView.h index 5dc7d2a..02308cf 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.h +++ b/TMQuiltView/TMQuiltView/TMQuiltView.h @@ -59,7 +59,7 @@ typedef enum { @property (nonatomic, assign) id dataSource; @property (nonatomic, assign) id delegate; -@property(nonatomic,retain) UIView *quiltHeaderView; +@property(nonatomic,retain) IBOutlet UIView *quiltHeaderView; // Returns the cell if it's visible and indexPath is valid. Returns nil otherwise - (TMQuiltViewCell *)cellAtIndexPath:(NSIndexPath*)indexPath; diff --git a/TMQuiltView/TMQuiltView/TMQuiltView.m b/TMQuiltView/TMQuiltView/TMQuiltView.m index 3f24f1b..2446410 100644 --- a/TMQuiltView/TMQuiltView/TMQuiltView.m +++ b/TMQuiltView/TMQuiltView/TMQuiltView.m @@ -151,15 +151,6 @@ - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { - if (self.subviews.count > 1) { - assert(false); //don't use too many views in quiltview, just only one can use to header - } - if (self.subviews.count == 1) { - _quiltHeaderView = [[self.subviews objectAtIndex:0] retain]; - CGRect headerFrame = self.quiltHeaderView.frame; - headerFrame.origin.y = 0; - self.quiltHeaderView.frame = headerFrame; - } super.alwaysBounceVertical = YES; [self addGestureRecognizer:self.tapGestureRecognizer]; _numberOfColumms = kTMQuiltViewDefaultColumns;