UITableView with fixed section headers

IosObjective CUitableview

Ios Problem Overview


Greets, I'm reading that the default behaviour of UITableView is to pin section header rows to the top of the table as you scroll through the sections until the next section pushes the previos section row out of view.

I have a UITableView inside a UIViewController and this does not seem to be the case.

Is that just the defualt behaviour for UITableViewController?

Here's some simplified code based on what I have. I'll show the UIController interface and each table view method I've implemented to create the table view. I have a helper data source class that helps me index my objects for use with the table.

    @interface MyUIViewController ()<UITableViewDelegate, UITableViewDataSource>
        @property (nonatomic, readonly) UITableView *myTableView;
        @property (nonatomic, readonly) MyCustomHelperDataSource *helperDataSource;
    @end
    
    //when section data is set, get details for each section and reload table on success
    - (void)setSectionData:(NSArray *)sections {
        super.sectionData = sections; //this array drives the sections
        
        //get additional data for section details
        [[RestKitService sharedClient] getSectionDetailsForSection:someId 
        success:^(RKObjectRequestOperation *operation, RKMappingResult *details) {
            NSLog(@"Got section details data");
            _helperDataSource = [[MyCustomHelperDataSource alloc] initWithSections:sections andDetails:details.array];
            [myTableView reloadData];
        } failure:^(RKObjectRequestOperation *operation, NSError *error) {
            NSLog(@"Failed getting section details");
        }];
    }
    
    #pragma mark <UITableViewDataSource, UITableViewDelegate>
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        if (!_helperDataSource) return 0;
    	return [_helperDataSource countSectionsWithDetails]; //number of section that have details rows, ignore any empty sections
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        //get the section object for the current section int
        SectionObject *section = [_helperDataSource sectionObjectForSection:section];
        //return the number of details rows for the section object at this section
        return [_helperDataSource countOfSectionDetails:section.sectionId];
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        
        UITableViewCell * cell;
    
        NSString *CellIdentifier = @"SectionDetailCell";
        
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
            cell.textLabel.font = [UIFont systemFontOfSize:12.0f];
        }
        
        //get the detail object for this section
        SectionObject *section = [_helperDataSource sectionObjectForSection:indexPath.section]; 
        
        NSArray* detailsForSection = [_helperDataSource detailsForSection:section.sectionId] ;
        SectionDetail *sd = (SectionDetail*)[detailsForSection objectAtIndex:indexPath.row];
        
        cell.textLabel.text = sd.displayText;
        cell.detailTextLabel.text = sd.subText;
        cell.detailTextLabel.textColor = [UIColor blueTextColor];
        
        return cell;
    }

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 50.0f;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 30.0f;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger) section {
    //get the section object for the current section
    SectionObject *section = [_helperDataSource sectionObjectForSection:section]; 
        
    NSString *title = @"%@ (%d)";

	return [NSString stringWithFormat:title, section.name, [_helperDataSource countOfSectionDetails:section.sectionId]];
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 260, 0)];
    header.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    
    header.backgroundColor = [UIColor darkBackgroundColor];

    SSLabel *label = [[SSLabel alloc] initWithFrame:CGRectMake(3, 3, 260, 24)];
    label.font = [UIFont boldSystemFontOfSize:10.0f];
    label.verticalTextAlignment = SSLabelVerticalTextAlignmentMiddle;
    label.backgroundColor = [UIColor clearColor];
    label.text = [self tableView:tableView titleForHeaderInSection:section];
    label.textColor = [UIColor whiteColor];
    label.shadowColor = [UIColor darkGrayColor];
    label.shadowOffset = CGSizeMake(1.0, 1.0);
    [header addSubview:label];
    
    return header;
}

Ios Solutions


Solution 1 - Ios

The headers only remain fixed (floating) when the UITableViewStyle property of the table is set to UITableViewStylePlain.

If you have it set to UITableViewStyleGrouped, the headers will scroll up with the cells (will not float).

Solution 2 - Ios

Change your TableView Style:

> self.tableview = [[UITableView alloc] initwithFrame:frame > style:UITableViewStyleGrouped];

As per apple documentation for UITableView:

> UITableViewStylePlain- A plain table view. Any section headers or > footers are displayed as inline separators and float when the table > view is scrolled. > > UITableViewStyleGrouped- A table view whose sections present distinct > groups of rows. The section headers and footers do not float.

Hope this small change will help you ..

Solution 3 - Ios

Swift 3.0

Create a ViewController with the UITableViewDelegate and UITableViewDataSource protocols. Then create a tableView inside it, declaring its style to be UITableViewStyle.grouped. This will fix the headers.

lazy var tableView: UITableView = {
    let view = UITableView(frame: UIScreen.main.bounds, style: UITableViewStyle.grouped)
    view.delegate = self
    view.dataSource = self
    view.separatorStyle = .none
    return view
}()

Solution 4 - Ios

You can also set the tableview's bounces property to NO. This will keep the section headers non-floating/static, but then you also lose the bounce property of the tableview.

Solution 5 - Ios

to make UITableView sections header not sticky or sticky:

  1. change the table view's style - make it grouped for not sticky & make it plain for sticky section headers - do not forget: you can do it from storyboard without writing code. (click on your table view and change it is style from the right Side/ component menu)

  2. if you have extra components such as custom views or etc. please check the table view's margins to create appropriate design. (such as height of header for sections & height of cell at index path, sections)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiontopwikView Question on Stackoverflow
Solution 1 - IosbachonkView Answer on Stackoverflow
Solution 2 - IosAshView Answer on Stackoverflow
Solution 3 - IosNursultan AskarbekulyView Answer on Stackoverflow
Solution 4 - IoskevinlView Answer on Stackoverflow
Solution 5 - IosBurcu KutluayView Answer on Stackoverflow