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 abad306..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); @@ -449,8 +466,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,8 +482,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]; + 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]; @@ -493,13 +511,34 @@ - (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]; + } + } } } - (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]; @@ -548,6 +587,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; } @@ -577,6 +617,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