Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize table header when using dynamic types

I have a TableViewController with a header. This header is a container, which links to another storyboard named Header.storyboard

TableViewController

Header.storyboard contains a stack view with some labels, that are dynamically typed.

Labels text comes from DB.

No regards to the text dimension or size I want to visualise it correctly.

enter image description here

I've used some answers from SO to get the header correctly resize, but without luck:

import UIKit

class TableViewController: UITableViewController {

    @IBOutlet weak var tableHeaderView: UIView!

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        // Dynamic sizing for the header view
        if let headerView = tableHeaderView {
            headerView.setNeedsLayout()
            headerView.layoutIfNeeded()

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

            // If we don't have this check, viewDidLayoutSubviews() will get
            // repeatedly, causing the app to hang.
            if height != headerFrame.size.height {
                headerFrame.size.height = height
                headerView.frame = headerFrame
                tableHeaderView = headerView
           }
       }
   }
}
like image 708
Laura Calinoiu Avatar asked Mar 01 '17 15:03

Laura Calinoiu


2 Answers

Table view header can be automatically resized

but with containers it likely will not work

use custom view instead for viewForHeaderInSection

class ViewController: UITableViewController {
    override func viewDidLoad() {
        tableView.estimatedSectionHeaderHeight = 10
        tableView.sectionHeaderHeight = UITableViewAutomaticDimension
    }
    override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let lab = UILabel()
        lab.text = "text \(section)"
        lab.font = UIFont.systemFont(ofSize: 10 * CGFloat(section) + 1)
        return lab
    }
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 5
    }
    //this method overriding is not necessary
    override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return UITableViewAutomaticDimension
    }
}

Result

like image 124
Andrew Avatar answered Sep 18 '22 18:09

Andrew


First, instead of giving the height to the view, you should give the label a height

class ViewController : UITableViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 40
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 4
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.backgroundColor = UIColor.yellow
    cell.textLabel?.text = "Baran"

    return cell

}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
    return heightForView()
}

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let headerView : UIView = UIView(frame: CGRect(x: 0, y: 20, width: self.view.frame.width, height: self.heightForView()))
    headerView.backgroundColor = UIColor.black

    let label : UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.heightForView()))
    label.numberOfLines = 0
    label.textAlignment = NSTextAlignment.center
    label.text = "Size To Fit Tutorial"
    label.font = UIFont(name: "Helvetica", size: 50)
    label.textColor = UIColor.white
    headerView.addSubview(label)

    return headerView
}

//Self Sizing height ....
func heightForLabel(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byCharWrapping
    label.font = font
    label.text = text
    label.sizeToFit()
    return label.frame.height
}

func heightForView() -> CGFloat{

    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width

    let text = "Size To Fit Tutorial"
    let font : UIFont!
    switch UIDevice.current.userInterfaceIdiom {
    case .pad:
        font = UIFont(name: "Helvetica", size: 35)
    case .phone:
        font = UIFont(name: "Helvetica", size: 50)
    default:
        font = UIFont(name: "Helvetica", size: 24)
    }
    let height = heightForLabel(text: text, font: font, width: screenWidth)

    return height
}
}

enter image description here

Hope this helps

like image 33
Baran Karaoğuz Avatar answered Sep 21 '22 18:09

Baran Karaoğuz