81

I have gone through Apple docs about UITableView class and delegate reference but couldn't find the way to set the table header height explicitly.

I set Table cell height using following delegate:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

and set section header/footer height using following delegates.

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section

Could anyone please help me to set the table header/footer height?

Thanks.

visakh7
  • 26,380
  • 8
  • 55
  • 69
Paresh Masani
  • 7,474
  • 12
  • 73
  • 139

17 Answers17

68

Just set the frame property of the tableHeaderView.

Roger
  • 15,793
  • 4
  • 51
  • 73
  • I already do that. I set my image to tableheaderview.I am not able to change table header's height. The thing is HeaderImaze size is 640x88 and it gets rescaled to 320x88 which is wrong so i want to set my table header height to 44 when the specified image resolution width is 640. – Paresh Masani Apr 07 '11 at 12:59
  • 1
    Hi Roger, I think your idea should work. I tried to set frame property using "plainTableView.tableHeaderView.frame = CGRectMake(0,0,320,44);" but nothing happens. Please note that my image size if 640x88 and I am assigning it to tableHeaderView. – Paresh Masani Apr 07 '11 at 13:24
  • Following worked for me. I couldn't change the table height but I reset the image height. if(headerImage.bounds.size.width == 640) [headerImage setFrame: CGRectMake(0, 0, headerImage.bounds.size.width, headerImage.bounds.size.height/2)]; – Paresh Masani Apr 07 '11 at 14:29
62

I found a nice hack. Add the below line after modifying the frame propery

self.tableView.tableHeaderView = self.tableView.tableHeaderView;

The trick is (I think) that the UITableView is caching the height (the frame actually) when you assign the view to the tableHeaderView property. The above line just assigns the height again.

Cristian Bica
  • 4,067
  • 27
  • 28
  • However, if you try to animate the change, it only seems to work in the shrinking direction. – Kudit Mar 25 '13 at 19:38
  • 1
    Animation or not, this is the fastest solution. Perfect :) – iPhoneNoob Feb 19 '16 at 11:39
  • 1
    Can't believe this was the solution! It works for making the header smaller & larger. For Swift I'm doing - tableView.tableHeaderView!.frame = CGRectMake(0, 0, self.view.frame.size.width, 100) tableView.tableHeaderView = self.tableView.tableHeaderView – Michael McKenna Jun 03 '16 at 13:39
43
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    sizeHeaderToFit()
}

private func sizeHeaderToFit() {
    let headerView = tableView.tableHeaderView!

    headerView.setNeedsLayout()
    headerView.layoutIfNeeded()

    let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
    var frame = headerView.frame
    frame.size.height = height
    headerView.frame = frame

    tableView.tableHeaderView = headerView
}

More details can be found here

Alessandro Francucci
  • 1,528
  • 17
  • 25
Kris
  • 1,538
  • 2
  • 16
  • 27
  • 1
    Awesome. Many thanks Kris. Your function still works great in viewDidAppear. It will be better than viewDidLayoutSubviews which is called many times. – truongky Nov 24 '16 at 03:16
  • 1
    @truongky No, viewDidLayoutSubviews will work eg on rotation or on window resize (eg iPad split screen), what is desired to be resized after it, viewWill/DidAppear will never update it and it will look wrong. – Nat Oct 02 '18 at 09:44
  • 3
    This is resulting in a freeze due to endless layout loops for me as of iOS 12.4 – Trev14 Aug 12 '19 at 22:14
10

In case you still need it, have you tried to set the property

self.tableView.tableHeaderView 

If you calculate the heigh you need, and set a new view for tableHeaderView:

CGRect frame = self.tableView.tableHeaderView.frame;
frame.size.height = newHeight;

self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:frame];

It should work.

biegleux
  • 13,179
  • 11
  • 45
  • 52
Fabio
  • 251
  • 4
  • 8
7

It works with me only if I set the footer/header of the tableview to nil first:

self.footer = self.searchTableView.tableFooterView;
CGRect frame = self.footer.frame;
frame.size.height = 200;
self.footer.frame = frame;
self.searchTableView.tableFooterView = nil;
self.searchTableView.tableFooterView = self.footer;

Make sure that self.footer is a strong reference to prevent the footer view from being deallocated

Hossam Ghareeb
  • 7,063
  • 3
  • 53
  • 64
4

Swift 4 - you can manage height with HEIGHT_VIEW,Just add this cods, Its working

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let HEIGHT_VIEW = 60
    tableView.tableFooterView?.frame.size = CGSize(width: tblView.frame.width, height: CGFloat(HEIGHT_VIEW))

    tableView.tableHeaderView?.frame.size = CGSize(width:tblView.frame.width, height: CGFloat(HEIGHT_VIEW))
}
Krunal Patel
  • 1,649
  • 1
  • 14
  • 22
2

Just create Footer Wrapper View using constructor UIView(frame:_) then if you are using xib file for FooterView, create view from xib and add as subView to wrapper view. then assign wrapper to tableView.tableFooterView = fixWrapper .

    let fixWrapper = UIView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.width, 54)) // dont remove
    let footer = UIView.viewFromNib("YourViewXibFileName") as! YourViewClassName
    fixWrapper.addSubview(footer)
    tableView.tableFooterView = fixWrapper
    tableFootterCostView = footer

It works perfectly for me! the point is to create footer view with constructor (frame:_). Even though you create UIView() and assign frame property it may not work.

Sergey Sahakyan
  • 723
  • 8
  • 15
2

If add a view as table header view in IB, set the frame of that view in IB in Tab 5(size inspector)

Yllow
  • 326
  • 4
  • 7
2

If you programatically set the tableHeaderView, then just set it inside viewDidLayoutSubviews.

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        setupTableViewHeader()
    }

    private func setupTableViewHeader() {
        // Something you do to set it up programatically...
        tableView.tableHeaderView = MyHeaderView.instanceFromNib() 
    }

If you didn't set it programatically, you need to do similar to what @Kris answered based on this link

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        sizeHeaderToFit()
    }

    private func sizeHeaderToFit() {
        if let headerView = tableView.tableHeaderView {
            headerView.setNeedsLayout()
            headerView.layoutIfNeeded()

            let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
            var frame = headerView.frame
            frame.size.height = height
            headerView.frame = frame

            tableView.tableHeaderView = headerView
        }
    }

meow2x
  • 2,056
  • 22
  • 27
2

@kris answer is helpful for me anyone want it in Objective-C.

Here is the code

-(void)viewDidLayoutSubviews{
     [super viewDidLayoutSubviews];
     [self sizeHeaderToFit];
}

-(void)sizeHeaderToFit{
     UIView *headerView = self.tableView.tableHeaderView;
     [headerView setNeedsLayout];
     [headerView layoutIfNeeded];
     CGFloat height = [headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
     CGRect frame = headerView.frame;
     frame.size.height = height;
     headerView.frame = frame;
     self.tableView.tableHeaderView = headerView;
}
Yogesh Patel
  • 1,893
  • 1
  • 20
  • 55
1

If you are using XIB for tableView's main headerView you can set XIB as a freeform set the Height as you want and unclick Autoresizing's top,bottom blocks and upper,lower arrows.Only horizontal pieces will be selected.Vertical will be unselected as I mentioned above.

1

You can create a UIView with the desired height (the width should be that of the UITableView), and inside it you can place a UIImageView with the picture of the proper dimensions: they won't stretch automatically.

You can also give margin above and below the inner UIImageView, by giving a higher height to the container view.

Additionally, you can assign a Translation transform in order to place the image in the middle of its container header view, for example.

Gabriel
  • 1,401
  • 13
  • 21
-1

If you changed height of tableView's headerView, just reset headerView's frame, then, reset headerView of tableView:

self.headerView.frame = newFrame;
self.tableView.tableHeaderView = self.headerView;
Meilbn
  • 582
  • 7
  • 8
  • This does so much more than required. Don't use it for such a simple task. Simple setNeedsLayout is enough in case you're describing. – Nat Oct 01 '18 at 13:57
-1

With autolayout you could do something like:

tableView.sectionHeaderHeight = UITableViewAutomaticDimension
tableView.estimatedSectionHeaderHeight = <your-header-height>

or if your headers are of different heights, go ahead and implement:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return <your-header-height>
}
Matti
  • 427
  • 1
  • 4
  • 13
-1

In Xcode 10 you can set header and footer of section hight from "Size Inspector" tab

Size Inspector header

mokagio
  • 16,391
  • 3
  • 51
  • 58
NinjaDeveloper
  • 1,620
  • 3
  • 19
  • 51
-2
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
}

or you can use like this also

tableView.estimatedSectionHeaderHeight 
Yannis
  • 1,682
  • 7
  • 27
  • 45
Mnsd
  • 37
  • 6
  • We aren't discussing about SEction header. it is about tableView header – Arthur Garza May 18 '18 at 20:20
  • I use the section header and footer as headers and footers for the table. So this is valid for me and was helpful. I found it easier than the other solutions. – David J Oct 13 '18 at 17:42
-3

Use table view default property :

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

Thanks

Mitesh Khatri
  • 3,935
  • 4
  • 44
  • 67