Skip to content

Commit

Permalink
The active section header view now stays pinned to the top of the tab…
Browse files Browse the repository at this point in the history
…le view (matching the behavior of UITableView)
  • Loading branch information
jboley committed Aug 11, 2011
1 parent a0dd103 commit 2dbc286
Showing 1 changed file with 45 additions and 28 deletions.
73 changes: 45 additions & 28 deletions lib/UIKit/TUITableView.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#import "TUITableView.h"
#import "TUINSView.h"

// header views need to be above the cells at all times
#define HEADER_Z_POSITION 1000

typedef struct {
CGFloat offset; // from beginning of section
CGFloat height;
Expand Down Expand Up @@ -130,6 +133,7 @@ - (TUIView *)headerView
if(_tableView.dataSource != nil && [_tableView.dataSource respondsToSelector:@selector(tableView:headerViewForSection:)]){
_headerView = [[_tableView.dataSource tableView:_tableView headerViewForSection:sectionIndex] retain];
_headerView.autoresizingMask = TUIViewAutoresizingFlexibleWidth;
_headerView.layer.zPosition = HEADER_Z_POSITION;
}
}
return _headerView;
Expand Down Expand Up @@ -219,6 +223,17 @@ - (NSInteger)numberOfRowsInSection:(NSInteger)section
return [[_sectionInfo objectAtIndex:section] numberOfRows];
}

- (CGRect)rectForSection:(NSInteger)section {
if(section >= 0 && section < [_sectionInfo count]){
TUITableViewSection *s = [_sectionInfo objectAtIndex:section];
CGFloat offset = [s sectionOffset];
CGFloat height = [s sectionHeight];
CGFloat y = _contentHeight - offset - height;
return CGRectMake(0, y, self.bounds.size.width, height);
}
return CGRectZero;
}

- (CGRect)rectForHeaderOfSection:(NSInteger)section {
if(section >= 0 && section < [_sectionInfo count]){
TUITableViewSection *s = [_sectionInfo objectAtIndex:section];
Expand Down Expand Up @@ -359,7 +374,7 @@ - (NSIndexSet *)indexesOfSectionsInRect:(CGRect)rect
NSMutableIndexSet *indexes = [[NSMutableIndexSet alloc] init];

for(int i = 0; i < [_sectionInfo count]; i++) {
if(CGRectIntersectsRect([self rectForHeaderOfSection:i], rect)){
if(CGRectIntersectsRect([self rectForSection:i], rect)){
[indexes addIndex:i];
}
}
Expand Down Expand Up @@ -522,52 +537,54 @@ - (BOOL)_preLayoutCells
*/
- (void)_layoutSectionHeaders:(BOOL)visibleHeadersNeedRelayout
{
if(visibleHeadersNeedRelayout) {
if(_visibleSectionHeaders != nil){
[_visibleSectionHeaders enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) {
if(index < [_sectionInfo count]) {
TUITableViewSection *section = [_sectionInfo objectAtIndex:index];
if(section.headerView != nil) {
section.headerView.frame = [self rectForHeaderOfSection:index];
[section.headerView setNeedsLayout];
}
}
}];
}
}

CGRect visible = [self visibleRect];

NSIndexSet *oldIndexes = _visibleSectionHeaders;
NSIndexSet *newIndexes = [self indexesOfSectionHeadersInRect:visible];
NSIndexSet *newIndexes = [self indexesOfSectionsInRect:visible];

NSMutableIndexSet *toRemove = [[oldIndexes mutableCopy] autorelease];
[toRemove removeIndexes:newIndexes];
NSMutableIndexSet *toAdd = [[newIndexes mutableCopy] autorelease];
[toAdd removeIndexes:oldIndexes];

// remove offscreen headers
[toRemove enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) {
// update the placement of all visible headers
__block TUIView *pinnedHeader = nil;
[newIndexes enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) {
if(index < [_sectionInfo count]) {
TUITableViewSection *section = [_sectionInfo objectAtIndex:index];
if(section.headerView != nil) {
[section.headerView removeFromSuperview];
CGRect headerFrame = [self rectForHeaderOfSection:index];

// check if this header needs to be pinned
if(CGRectGetMaxY(headerFrame) > CGRectGetMaxY(visible)) {
headerFrame.origin.y = CGRectGetMaxY(visible) - headerFrame.size.height;
pinnedHeader = section.headerView;
}
else if((pinnedHeader != nil) && (CGRectGetMaxY(headerFrame) > pinnedHeader.frame.origin.y)) {
// this header is intersecting with the pinned header, so we push the pinned header upwards.
CGRect pinnedHeaderFrame = pinnedHeader.frame;
pinnedHeaderFrame.origin.y = CGRectGetMaxY(headerFrame);
pinnedHeader.frame = pinnedHeaderFrame;
}

section.headerView.frame = headerFrame;
[section.headerView setNeedsLayout];

if (section.headerView.superview == nil)
[self addSubview:section.headerView];
}
}
[_visibleSectionHeaders removeIndex:index];
[_visibleSectionHeaders addIndex:index];
}];

// add new headers
[toAdd enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) {
if(index < [_sectionInfo count]){
// remove offscreen headers
[toRemove enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) {
if(index < [_sectionInfo count]) {
TUITableViewSection *section = [_sectionInfo objectAtIndex:index];
if(section.headerView != nil) {
section.headerView.frame = [self rectForHeaderOfSection:index];
[section.headerView setNeedsLayout];
[self addSubview:section.headerView];
[section.headerView removeFromSuperview];
}
}
[_visibleSectionHeaders addIndex:index];
[_visibleSectionHeaders removeIndex:index];
}];
}

Expand Down

0 comments on commit 2dbc286

Please sign in to comment.