114

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;
}
Meet Doshi
  • 4,241
  • 10
  • 40
  • 81
topwik
  • 3,487
  • 8
  • 41
  • 65
  • That should work. Show some code. – Matthias Bauch Jul 10 '13 at 23:48
  • That is a completely fine way to use a UITableView, and should work with the headers. What aren't the headers doing in your case? – Eric Jul 11 '13 at 00:15
  • @Eric the headers are scrolling with the rows. They are not stopping at the top of the table while I scroll. I've added the code I'm using to generate my table view. It's a UITableView inside a UIViewController. – topwik Jul 11 '13 at 00:30

5 Answers5

332

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).

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
bachonk
  • 3,924
  • 1
  • 14
  • 14
  • 4
    my tableview style is UITableViewStylePlain, but it scroll up with the cells either. – yudun1989 Jun 10 '14 at 14:52
  • 8
    There's a couple possible explanations for this. One important note is that the headers will only remain fixed for cells within its section. So, if you have a header in section 0, it will not remain fixed for cells in section 1. Another possible explanation is that you're not initializing your UITableView with the proper style. It is recommended that you use `initWithStyle:UITableViewStylePlain`, as calling something like tableView.style = UITableViewStylePlain will not work. – bachonk Jun 10 '14 at 16:35
  • 1
    UITableViewStyleGrouped makes header/footer fixed with other cells, while UITableViewStylePlain makes the header/footer "float" when header/footer reach the top/bottom of tableview. – StoneLam Dec 23 '17 at 01:57
  • @bachonk i am using a stretchable header view. and my style is UITableViewStyleGrouped. i want to fix the header when scrolling up. if i make it UITableViewStylePlain then the header is getting fixed in the middle of the screen, i want to scroll the header down, but when scrolling up i want it to fix on the first row.. can it be possible? – Gorib Developer Aug 02 '18 at 12:15
5

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 ..

Ash
  • 5,525
  • 1
  • 40
  • 34
  • 2
    this appears to be exactly the opposite of what the question requested - it should be `Plain`, not `Grouped` – CupawnTae Dec 02 '16 at 15:50
3

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
}()
0

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.

kevinl
  • 4,194
  • 6
  • 37
  • 55
0

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)

Burcu Kutluay
  • 472
  • 6
  • 14