170

I want to add a table header (not section headers) like in the contacts app for example: enter image description here

exactly like that - a label beside an image above of the table.

I want the all view be scrollable so I can't place those outside of the table.

How can I do that?

AMM
  • 2,195
  • 2
  • 20
  • 28

5 Answers5

247

UITableView has a tableHeaderView property. Set that to whatever view you want up there.

Use a new UIView as a container, add a text label and an image view to that new UIView, then set tableHeaderView to the new view.

For example, in a UITableViewController:

-(void)viewDidLoad
{
     // ...
     UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(XXX, YYY, XXX, YYY)];
     UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(XXX, YYY, XXX, YYY)];
     [headerView addSubview:imageView];
     UILabel *labelView = [[UILabel alloc] initWithFrame:CGRectMake(XXX, YYY, XXX, YYY)];
     [headerView addSubview:labelView];
     self.tableView.tableHeaderView = headerView;
     [imageView release];
     [labelView release];
     [headerView release];
     // ...
} 
Paras Joshi
  • 20,427
  • 11
  • 57
  • 70
peterjb
  • 3,189
  • 2
  • 17
  • 12
  • Great! Thanks it's working. Is there any property of making the tableview cells grow as big as the text inside? – AMM Mar 26 '11 at 16:57
  • In order to do that, you need to be able to calculate the height of the cell given a string, and pass that value in for heightForRowAtIndexPath. You can use NSString's method sizeWithFont:constrainedToSize: function to figure out the height of the text when constrained to a size. – Mark May 24 '13 at 15:31
  • Add it after layout, or it's size will not your wanted. And viewDidLoad is a good place. – BollMose Jul 06 '15 at 05:21
  • Is it a good practice to set the geometry of the view during in viewDidLoad phase? – Nandish A Mar 24 '16 at 17:37
  • if you use this approach, how do you get the header view to float? I just tried and ensured that my tableview was set `Plain` Style – panthor314 Aug 26 '16 at 19:53
  • 1
    ok if you set the header view in the tables source it seems to work, make sure to set the height as well: example:`public override UIView GetViewForHeader(UITableView tableView, nint section) { return headerView; } public override nfloat GetHeightForHeader(UITableView tableView, nint section) { return headerView.Frame.Height; }` – panthor314 Aug 26 '16 at 20:01
  • I want to do exactly the same thing but I have a UISearchBar at the top. The code above [answer not comment above] replaces the UISearchBar for some reason. Does anyone know how, I can prevent this from happening? – Charles Robertson Nov 18 '16 at 00:11
194

You can do it pretty easy in Interface Builder. Just create a view with a table and drop another view onto the table. This will become the table header view. Add your labels and image to that view. See the pic below for the view hierarchy. View Hierarchy in Interface Builder

Kirby Todd
  • 11,254
  • 3
  • 32
  • 60
  • 12
    I prefer this answer since why write code when I can neatly set it up and position it in IB – Besi Jun 26 '12 at 06:16
  • 1
    awesome thanks for the hint. BTW you don't need a scroll view in your header in case anyone else was wondering or trying that. It uses the UITableView's ScrollView for your Header, since the Header is technically a part of the UITableView – Rob R. Jan 28 '13 at 16:49
  • 2
    Worth to mention how it works in StoryBoard editor now: http://stackoverflow.com/q/7841167/926907 – Dmitry Zaytsev May 29 '13 at 16:57
  • Don't use a nib for this. Takes longer to load. Write it in code. For reusability create a custom class & instantiate... – Charles Robertson Nov 18 '16 at 00:01
  • 1
    It won't let me add a height constraint to the header view. – Ian Warburton Jan 05 '17 at 18:51
15

In Swift:

override func viewDidLoad() {
    super.viewDidLoad()

    // We set the table view header.
    let cellTableViewHeader = tableView.dequeueReusableCellWithIdentifier(TableViewController.tableViewHeaderCustomCellIdentifier) as! UITableViewCell
    cellTableViewHeader.frame = CGRectMake(0, 0, self.tableView.bounds.width, self.heightCache[TableViewController.tableViewHeaderCustomCellIdentifier]!)
    self.tableView.tableHeaderView = cellTableViewHeader

    // We set the table view footer, just know that it will also remove extra cells from tableview.
    let cellTableViewFooter = tableView.dequeueReusableCellWithIdentifier(TableViewController.tableViewFooterCustomCellIdentifier) as! UITableViewCell
    cellTableViewFooter.frame = CGRectMake(0, 0, self.tableView.bounds.width, self.heightCache[TableViewController.tableViewFooterCustomCellIdentifier]!)
    self.tableView.tableFooterView = cellTableViewFooter
}
King-Wizard
  • 15,628
  • 6
  • 82
  • 76
  • Using this approach for iOS 7 or above will trigger a runtime warning: "no index path for table cell being reused". To avoid this error, reference [link](http://stackoverflow.com/questions/12772197/what-is-the-meaning-of-the-no-index-path-for-table-cell-being-reused-message-i) – baskInEminence Sep 02 '16 at 18:16
11

You can also simply create ONLY a UIView in Interface builder and drag & drop the ImageView and UILabel (to make it look like your desired header) and then use that.

Once your UIView looks like the way you want it too, you can programmatically initialize it from the XIB and add to your UITableView. In other words, you dont have to design the ENTIRE table in IB. Just the headerView (this way the header view can be reused in other tables as well)

For example I have a custom UIView for one of my table headers. The view is managed by a xib file called "CustomHeaderView" and it is loaded into the table header using the following code in my UITableViewController subclass:

-(UIView *) customHeaderView {
    if (!customHeaderView) {
        [[NSBundle mainBundle] loadNibNamed:@"CustomHeaderView" owner:self options:nil];
    }

    return customHeaderView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Set the CustomerHeaderView as the tables header view 
    self.tableView.tableHeaderView = self.customHeaderView;
}
iansari
  • 354
  • 3
  • 12
-38
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {

    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,tableView.frame.size.width,30)];
    headerView.backgroundColor=[[UIColor redColor]colorWithAlphaComponent:0.5f];
    headerView.layer.borderColor=[UIColor blackColor].CGColor;
    headerView.layer.borderWidth=1.0f;

    UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5,100,20)];

    headerLabel.textAlignment = NSTextAlignmentRight;
    headerLabel.text = @"LeadCode ";
    //headerLabel.textColor=[UIColor whiteColor];
    headerLabel.backgroundColor = [UIColor clearColor];


    [headerView addSubview:headerLabel];

    UILabel *headerLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(60, 0, headerView.frame.size.width-120.0, headerView.frame.size.height)];

    headerLabel1.textAlignment = NSTextAlignmentRight;
    headerLabel1.text = @"LeadName";
    headerLabel.textColor=[UIColor whiteColor];
    headerLabel1.backgroundColor = [UIColor clearColor];

    [headerView addSubview:headerLabel1];

    return headerView;

}
Krishna Raj Salim
  • 7,331
  • 5
  • 34
  • 66
Priyam
  • 69
  • 1
  • 3