16

I have a UITableView which I am able to add a header view to fairly easily. Many apps (like Facebook, for viewing events) have a headerView that when you pull down, the header view stays put but the rest of the table (the UITableViewCell's) are bouncing. When scrolling up the header disappears. How can I achieve this functionality?

Right now when I pull down the UITableView, even the headerView bounces as well

KVISH
  • 12,923
  • 17
  • 86
  • 162
  • When you say "bounce" do you mean scroll up / down past the headers? – Aaron May 16 '13 at 14:38
  • Basically when I scroll down, header stays put. When I scroll up, header disappears. THis is the tableHeaderView – KVISH May 16 '13 at 14:43
  • OK - I checked out the Facebook app's event table view. It looks like it has the default behavior. How many sections and rows in those sections do you have in your table view? Perhaps you don't have enough to get the effect you want? – Aaron May 16 '13 at 15:40
  • So you want the table's single header view to behave like a section header right? – Aaron May 16 '13 at 17:13

4 Answers4

37

You can achieve this effect quite easily by adding a subview to the header view and adjusting its frame or transform when the table view is scrolled beyond the top, i.e. the y component of its contentOffset becomes negative.

Example (in a UITableViewController subclass):

- (void)viewDidLoad
{
    [super viewDidLoad];
    CGFloat headerHeight = 64.0f;
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, headerHeight)];
    UIView *headerContentView = [[UIView alloc] initWithFrame:headerView.bounds];
    headerContentView.backgroundColor = [UIColor greenColor];
    headerContentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [headerView addSubview:headerContentView];
    self.tableView.tableHeaderView = headerView;
}

//Note: UITableView is a subclass of UIScrollView, so we
//      can use UIScrollViewDelegate methods.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat offsetY = scrollView.contentOffset.y;
    UIView *headerContentView = self.tableView.tableHeaderView.subviews[0];
    headerContentView.transform = CGAffineTransformMakeTranslation(0, MIN(offsetY, 0));
}

(to keep it simple, I've just used the first subview of the actual header view in scrollViewDidScroll:, you may want to use a property for that instead.)

omz
  • 53,243
  • 5
  • 129
  • 141
  • 2
    The real gem to this solution is to use a subview in the tableHeaderView. I tried to do this without a subview and got very strange results, so the subview is key. – levigroker Mar 05 '14 at 22:24
  • 1
    Your solution is the best :D – Linh Nguyen Jun 03 '15 at 17:37
  • If You want to stuck the tableview header on the top then applied this ammended code.. - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetY = scrollView.contentOffset.y; UIView *headerContentView = self.tableView.tableHeaderView.subviews[0]; if(offsetY >0){ headerContentView.transform = CGAffineTransformMakeTranslation(0, offsetY); } else{ headerContentView.transform = CGAffineTransformMakeTranslation(0, MIN(offsetY, 0)); } } – g212gs Aug 03 '15 at 11:08
  • Fantastic. And you can use @g212gs' change to make sure the header does not move. – ghr Jul 04 '17 at 03:51
  • Note that if there is a button in the header view, while it will always be visible it will become progressively unresponsive (from bottom to top of the button) as the table is scrolled up until the point where it is totally unresponsive once the table has been scrolled up as much as the height of the header or more i.e. scrolling affects touches on the button. So this is not a solution if you have buttons in the header. – ghr Jul 04 '17 at 23:09
0

Your UITableView is most likely working properly. Section headers are sticky by default in Plain style tables. Meaning as you scroll down the header stays at the top of the UITableView's frame until the next section header pushes it out of the way. The opposite occurs when you scroll up. Conversely you get the sticky behavior on section footers at the bottom of the UITableView's frame.

EDIT Misunderstood the original question:

I would suggest using a section header rather than the table view header to get the sticky behavior you're looking for.

Include a section in your data with no rows and put your table header's view in that section header view.

Aaron
  • 7,055
  • 2
  • 38
  • 53
0

you can use this line in view did load: (swift 5.6)

tableView.bounces = false
Mohammad Daihan
  • 538
  • 4
  • 15
-1

There is 2 ways you can set the table header:

  • Using the .tableHeaderView property directly (this header scrolls with the table)

  • Overriding the - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section function (this header stays static with the section)

By the sounds of it you should use the 2nd method instead of using the .tableHeaderView property

Don
  • 43
  • 2
  • I don't think this is correct. My section headers scroll up and down, and stick to the top of the table views as you scroll and until another section header pushes it out of the way. – Aaron May 16 '13 at 16:13
  • `tableHeaderView` is a header for the entire table, where as `viewForHeaderInSection` puts a header on each section. – Aaron May 16 '13 at 17:12