Change Default Scrolling Behavior of UITableView Section Header

IosIphoneUitableviewCocoa Touch

Ios Problem Overview


I have a UITableView with two sections. It is a simple table view. I am using viewForHeaderInSection to create custom views for these headers. So far, so good.

The default scrolling behavior is that when a section is encountered, the section header stays anchored below the Nav bar, until the next section scrolls into view.

My question is this: can I change the default behavior so that the section headers do NOT stay anchored at the top, but rather, scroll under the nav bar with the rest of the section rows?

Am I missing something obvious?

Thanks.

Ios Solutions


Solution 1 - Ios

The way I solved this problem is to adjust the contentOffset according to the contentInset in the UITableViewControllerDelegate (extends UIScrollViewDelegate) like this:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
       CGFloat sectionHeaderHeight = 40;
   if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
	   scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
   } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
	   scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
   }
}

Only problem here is that it looses a little bit of bounce when scrolling back to the top.


{NOTE: The "40" should be the exact height of YOUR section 0 header. If you use a number that is bigger than your section 0 header height, you'll see that finger-feel is affected (try like "1000" and you'll see the bounce behaviour is sort of weird at the top). if the number matches your section 0 header height, finger feel seems to be either perfect or near-perfect.}

Solution 2 - Ios

You can also add a section with zero rows at the top and simply use the footer of the previous section as a header for the next.

Solution 3 - Ios

Were it me doing this, I'd take advantage of the fact that UITableViews in the Plain style have the sticky headers and ones in the Grouped style do not. I'd probably at least try using a custom table cell to mimic the appearance of Plain cells in a Grouped table.

I haven't actually tried this so it may not work, but that's what I'd suggest doing.

Solution 4 - Ios

I know it comes late, but I have found the definitive solution!

What you want to do is if you have 10 sections, let the dataSource return 20. Use even numbers for section headers, and odd numbers for section content. something like this

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section%2 == 0) {
        return 0;
    }else {
        return 5;
    }
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        return [NSString stringWithFormat:@"%i", section+1];
    }else {
        return nil;
    }
}

Voilá! :D

Solution 5 - Ios

Originally posted [Here][1], a quick solution using the IB. The same can be done programmatically though quite simply.

> A probably easier way to achieve this (using IB): > > Drag a UIView onto your TableView to make it its header view. > > 1. Set that header view height to 100px > 2. Set the tableview contentInset (top) to -100 > 3. Section headers will now scroll just like any regular cell.

Some people commented saying that this solution hides the first header, however I have not noticed any such issue. It worked perfectly for me and was by far the simplest solution that I've seen so far.

[1]: https://stackoverflow.com/a/4295687/1669034 "Answer by @samvermette"

Solution 6 - Ios

There are several things that need done to solve this problem in a non-hacky manner:

  1. Set the table view style to UITableViewStyleGrouped
  2. Set the table view backgroundColor to [UIColor clearColor]
  3. Set the backgroundView on each table view cell to an empty view with backgroundColor [UIColor clearColor]
  4. If necessary, set the table view rowHeight appropriately, or override tableView:heightForRowAtIndexPath: if individual rows have different heights.

Solution 7 - Ios

I was not happy with the solutions described here so far, so I tried to combine them. The result is the following code, inspired by @awulf and @cescofry. It works for me because I have no real table view header. If you already have a table view header, you may have to adjust the height.

// Set the edge inset
self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0);

// Add a transparent UIView with the height of the section header (ARC enabled)
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]];

Solution 8 - Ios

Just change TableView Style:

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

UITableViewStyle Documentation:

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

Solution 9 - Ios

Select Grouped TableView style

Select Grouped Table View style from your tableView's Attribute Inspector in storyboard.

Solution 10 - Ios

Set the headerView of the table with a transparent view with the same height of the header in section view. Also initi the tableview with a y frame at -height.

self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)];

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease];
[self.tableView setTableHeaderView:headerView];

Solution 11 - 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 12 - Ios

I found an alternative solution, use the first cell of each section instead a real header section, this solution don't appears so clean, but works so fine, you can use a defined prototype cell for your headers section, and in the method cellForRowAtIndexPath ask for the indexPath.row==0, if true, use the header section prototype cell, else use your default prototype cell.

Solution 13 - Ios

Now that the grouped style looks basically the same as the plain style in iOS 7 (in terms of flatness and background), for us the best and easiest (i.e. least hacky) fix was to simply change the table view's style to grouped. Jacking with contentInsets was always a problem when we integrated a scroll-away nav bar at the top. With a grouped table view style, it looks exactly the same (with our cells) and the section headers stay fixed. No scrolling weirdness.

Solution 14 - Ios

Assign a negative inset to your tableView. If you have 22px high section headers, and you don't want them to be sticky, right after you reloadData add:

self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); 
self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 

Works like a charm for me. Works for section footers as well, just assign the negative inset on the bottom instead.

Solution 15 - Ios

I add the table to a Scroll View and that seems to work well.

Solution 16 - Ios

Check my answer here. This is the easiest way to implement the non-floating section headers without any hacks.

Solution 17 - Ios

@LocoMike's answer best fitted my tableView, however it broke when using footers as well. So, this is the corrected solution when using headers and footers:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
	return (self.sections.count + 1) * 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
	if (section % 3 != 1) {
		return 0;
	}
	section = section / 3;
	...
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
	if (section % 3 != 0) {
		return nil;
	}
	section = section / 3;
	...
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
	if (section % 3 != 0) {
		return 0;
	}
	section = section / 3;
	...
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
	if (section % 3 != 2) {
		return 0;
	}
	section = section / 3;
	...
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
	if (section % 3 != 0) {
		return nil;
	}
	section = section / 3;
	...
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
	if (section % 3 != 2) {
		return nil;
	}
	section = section / 3;
	...
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
	int section = indexPath.section;
	section = section / 3;
	...
}

Solution 18 - Ios

Swift version of @awulf answer, which works great!

func scrollViewDidScroll(scrollView: UIScrollView) {
    let sectionHeight: CGFloat = 80
    if scrollView.contentOffset.y <= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0)
    }else if scrollView.contentOffset.y >= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0)
    }
}

Solution 19 - Ios

I've learned that just setting the tableHeaderView property does it, i.e. :

 tableView.tableHeaderView = customView;

and that's it.

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
QuestiondavidjhinsonView Question on Stackoverflow
Solution 1 - IosawulfView Answer on Stackoverflow
Solution 2 - IosvoidSternView Answer on Stackoverflow
Solution 3 - IosColin BarrettView Answer on Stackoverflow
Solution 4 - IosLocoMikeView Answer on Stackoverflow
Solution 5 - IosDocView Answer on Stackoverflow
Solution 6 - IosNeil GallView Answer on Stackoverflow
Solution 7 - IosThomas KekeisenView Answer on Stackoverflow
Solution 8 - IosArthur SView Answer on Stackoverflow
Solution 9 - IosArjun ShuklaView Answer on Stackoverflow
Solution 10 - IoscescofryView Answer on Stackoverflow
Solution 11 - IosAshView Answer on Stackoverflow
Solution 12 - IosAlexBBView Answer on Stackoverflow
Solution 13 - IosGreg CombsView Answer on Stackoverflow
Solution 14 - IosMike AView Answer on Stackoverflow
Solution 15 - IosDolbexView Answer on Stackoverflow
Solution 16 - IosanemoView Answer on Stackoverflow
Solution 17 - IosmarmorView Answer on Stackoverflow
Solution 18 - IosJeffView Answer on Stackoverflow
Solution 19 - IosSoniView Answer on Stackoverflow