Ok, i know it is late but i had to do it.
I have spent 10 hours by now searching for a working solution but did not find a complete answer. Did found some hints but difficult for starters to understand. So i had to put in my 2 cents and complete the answer.
As it has been suggested in the few of the answers the only working solution that i was able to implement is by inserting normal cells in the table view and handle them as Section Headers, but the better way to achieve it is by inserting these cells at row 0 of every section. This way we can handle these custom non-floating headers very easily.
So, the steps are.
1. Implement UITableView with style UITableViewStylePlain.
-(void) loadView
{
[super loadView];
UITableView *tblView =[[UITableView alloc] initWithFrame:CGRectMake(0, frame.origin.y, frame.size.width, frame.size.height-44-61-frame.origin.y) style:UITableViewStylePlain];
tblView.delegate=self;
tblView.dataSource=self;
tblView.tag=2;
tblView.backgroundColor=[UIColor clearColor];
tblView.separatorStyle = UITableViewCellSeparatorStyleNone;
}
2. Implement titleForHeaderInSection as usual ( you can get this value by using your own logic, but I prefer to use standard delegates ).
- (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *headerTitle = [sectionArray objectAtIndex:section];
return headerTitle;
}
3. Immplement numberOfSectionsInTableView as usual
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
int sectionCount = [sectionArray count];
return sectionCount;
}
4. Implement numberOfRowsInSection as usual.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int rowCount = [[cellArray objectAtIndex:section] count];
return rowCount +1; //+1 for the extra row which we will fake for the Section Header
}
5. Return 0.0f in heightForHeaderInSection.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.0f;
}
6. DO NOT implement viewForHeaderInSection. Remove the method completely instead of returning nil.
7. In heightForRowAtIndexPath. Check if(indexpath.row == 0) and return the desired cell height for the section header, else return the height of the cell.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 0)
{
return 80; //Height for the section header
}
else
{
return 70; //Height for the normal cell
}
}
8. Now in cellForRowAtIndexPath, check if(indexpath.row == 0) and implement the cell as you want the section header to be and set the selection style to none. ELSE implement the cell as you want the normal cell to be.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0)
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SectionCell"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone; //So that the section header does not appear selected
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SectionHeaderBackground"]];
}
cell.textLabel.text = [tableView.dataSource tableView:tableView titleForHeaderInSection:indexPath.section];
return cell;
}
else
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleGray; //So that the normal cell looks selected
cell.backgroundView =[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellBackground"]]autorelease];
cell.selectedBackgroundView=[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SelectedCellBackground"]] autorelease];
}
cell.textLabel.text = [[cellArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row -1]; //row -1 to compensate for the extra header row
return cell;
}
}
9. Now implement willSelectRowAtIndexPath and return nil if indexpath.row == 0. This will care that didSelectRowAtIndexPath never gets fired for the Section header row.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0)
{
return nil;
}
return indexPath;
}
10. And finally in didSelectRowAtIndexPath, check if(indexpath.row != 0) and proceed.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row != 0)
{
int row = indexPath.row -1; //Now use 'row' in place of indexPath.row
//Do what ever you want the selection to perform
}
}
With this you are done. You now have a perfectly scrolling, non-floating section header.