Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add header view #15

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
24 changes: 24 additions & 0 deletions TMQuiltView.podspec
Original file line number Diff line number Diff line change
@@ -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" => "[email protected]" }
s.source = { :git => "https://github.com/1000Memories/TMQuiltView.git", :commit => "99a0f20259b12695c5c233e3921f88061d450b75" }
s.platform = :ios

s.source_files = 'TMQuiltView/TMQuiltView/*.{h,m}'
end
5 changes: 2 additions & 3 deletions TMQuiltView/TMQuiltView/TMQuiltView.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ typedef enum {

@end

@interface TMQuiltView : UIScrollView
@interface TMQuiltView : UIScrollView <UIGestureRecognizerDelegate>

@property (nonatomic, assign) id<TMQuiltViewDataSource> dataSource;
@property (nonatomic, assign) id<TMQuiltViewDelegate> delegate;

@property(nonatomic,retain) IBOutlet UIView *quiltHeaderView;
// Returns the cell if it's visible and indexPath is valid. Returns nil otherwise
- (TMQuiltViewCell *)cellAtIndexPath:(NSIndexPath*)indexPath;

Expand All @@ -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;
Expand Down
92 changes: 85 additions & 7 deletions TMQuiltView/TMQuiltView/TMQuiltView.m
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -72,7 +74,7 @@ @implementation TMQuiltView
@synthesize rowsToInsert = _rowsToInsert;

@synthesize tapGestureRecognizer = _tapGestureRecognizer;

@synthesize quiltHeaderView = _quiltHeaderView;
#pragma mark - Memory Management

- (void)dealloc {
Expand Down Expand Up @@ -122,6 +124,32 @@ - (void)recycleViews {
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
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;
}


- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
super.alwaysBounceVertical = YES;
[self addGestureRecognizer:self.tapGestureRecognizer];
Expand All @@ -130,6 +158,22 @@ - (id)initWithFrame:(CGRect)frame
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<TMQuiltViewDelegate>)delegate {
[super setDelegate:delegate];
}
Expand Down Expand Up @@ -315,7 +359,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++) {
Expand Down Expand Up @@ -397,7 +445,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);
Expand Down Expand Up @@ -449,8 +497,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]) {
Expand All @@ -466,8 +513,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];
Expand All @@ -493,13 +542,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];
Expand Down Expand Up @@ -548,6 +618,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;
}
Expand Down Expand Up @@ -577,6 +648,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
5 changes: 5 additions & 0 deletions TMQuiltViewDemo/TMQuiltViewDemo/TMDemoQuiltViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down