How do I set the height of tableHeaderView (UITableView) with autolayout?

后端 未结 12 1168
后悔当初
后悔当初 2020-11-27 10:23

I\'m been smashing my head against the wall with this for last 3 or 4 hours and I can\'t seem to figure it out. I have a UIViewController with a full screen UITableView insi

相关标签:
12条回答
  • 2020-11-27 10:49

    You need to use the UIView systemLayoutSizeFittingSize: method to obtain the minimum bounding size of your header view.

    I provide further discussion on using this API in this Q/A:

    How to resize superview to fit all subviews with autolayout?

    0 讨论(0)
  • 2020-11-27 10:53

    I've found an elegant way to way to use auto layout to resize table headers, with and without animation.

    Simply add this to your View Controller.

    func sizeHeaderToFit(tableView: UITableView) {
        if let headerView = tableView.tableHeaderView {
            let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
            var frame = headerView.frame
            frame.size.height = height
            headerView.frame = frame
            tableView.tableHeaderView = headerView
            headerView.setNeedsLayout()
            headerView.layoutIfNeeded()
        }
    }
    

    To resize according to a dynamically changing label:

    @IBAction func addMoreText(sender: AnyObject) {
        self.label.text = self.label.text! + "\nThis header can dynamically resize according to its contents."
    }
    
    override func viewDidLayoutSubviews() {
        // viewDidLayoutSubviews is called when labels change.
        super.viewDidLayoutSubviews()
        sizeHeaderToFit(tableView)
    }
    

    To animate a resize according to a changes in a constraint:

    @IBOutlet weak var makeThisTallerHeight: NSLayoutConstraint!
    
    @IBAction func makeThisTaller(sender: AnyObject) {
    
        UIView.animateWithDuration(0.3) {
            self.tableView.beginUpdates()
            self.makeThisTallerHeight.constant += 20
            self.sizeHeaderToFit(self.tableView)
            self.tableView.endUpdates()
        }
    }
    

    See the AutoResizingHeader project to see this in action. https://github.com/p-sun/Swift2-iOS9-UI

    0 讨论(0)
  • 2020-11-27 10:54

    It works for both header view and footer just replace the header with footer

    func sizeHeaderToFit() {
        if 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
        }
    }
    
    0 讨论(0)
  • 2020-11-27 10:56

    In my case viewDidLayoutSubviews worked better. viewWillLayoutSubviews causes white lines of a tableView to appear. Also I added checking if my headerView object already exists.

    - (void)viewDidLayoutSubviews
    {
        [super viewDidLayoutSubviews];
    
        if ( ! self.userHeaderView ) {
            // Setup HeaderView
            self.userHeaderView = [[[NSBundle mainBundle] loadNibNamed:@"SSUserHeaderView" owner:self options:nil] objectAtIndex:0];
            [self.userHeaderView setNeedsLayout];
            [self.userHeaderView layoutIfNeeded];
            CGFloat height = [self.userHeaderView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
            CGRect headerFrame = self.userHeaderView.frame;
            headerFrame.size.height = height;
            self.userHeaderView.frame = headerFrame;
            self.tableView.tableHeaderView = self.userHeaderView;
    
            // Update HeaderView with data
            [self.userHeaderView updateWithProfileData];
        }
    }
    
    0 讨论(0)
  • 2020-11-27 11:01

    For iOS 12 and above, the following steps will ensure autolayout works properly in both your table and the header.

    1. Create your tableView first, then the header.
    2. At the end of your header creation code, call:
    [headerV setNeedsLayout];
    [headerV layoutIfNeeded];
    
    1. Upon orientation change, mark the header for layout again and reload the table, this needs to happen slightly after the orientation change is reported:
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 *NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    
      [tableV.tableHeaderView setNeedsLayout];
      [tableV.tableHeaderView layoutIfNeeded];
      [tableV reloadData];});
    
    0 讨论(0)
  • 2020-11-27 11:04

    This solution resizes the tableHeaderView and avoids infinite loop in the viewDidLayoutSubviews() method I was having with some of the other answers here:

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        if let headerView = tableView.tableHeaderView {
            let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
            var headerFrame = headerView.frame
    
            // comparison necessary to avoid infinite loop
            if height != headerFrame.size.height {
                headerFrame.size.height = height
                headerView.frame = headerFrame
                tableView.tableHeaderView = headerView
            }
        }
    }
    

    See also this post: https://stackoverflow.com/a/34689293/1245231

    0 讨论(0)
提交回复
热议问题