Reputation: 6238
Hi I was wondering how i'd go for implementing a custom header for my UITableView
and use it's autolayout for correct positioning.
I can display the cell right now but neither horizontal or vertical autolayout is applied.
in my tableViewController, I set a headerView variable to my custom nib as such:
@IBOutlet var view: UIView!
override init(frame: CGRect) { // for using CustomView in code
super.init(frame: frame)
self.setup()
}
required init(coder aDecoder: NSCoder) { // for using CustomView in IB
super.init(coder: aDecoder)
self.setup()
}
private func setup() {
NSBundle.mainBundle().loadNibNamed("CustomHeader", owner: self, options: nil)
self.addSubview(view)
}
which in the view class calls:
override init(frame: CGRect) { // for using CustomView in code
super.init(frame: frame)
self.setup()
}
required init(coder aDecoder: NSCoder) { // for using CustomView in IB
super.init(coder: aDecoder)
self.setup()
}
private func setup() {
NSBundle.mainBundle().loadNibNamed("ChallengeHeader", owner: self, options: nil)
self.addSubview(view)
}
It has some dummy content and I set a dynamic text to a label inside. The constraints are set up correctly I have it working fine for the table cells.
I have this for displaying the view as header
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if let view = headerView {
return view
}
return nil
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if let head = headerView {
head.setNeedsLayout()
head.layoutIfNeeded()
let height = head.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
let headerFrame = head.frame
Debug.log("Header Height \(height)")
return 100.0
}
return 0
}
Currently I'm returning the 100.0 since height is always 0, so what am I missing here to make the autolayout do it's work? Or do I need to set f/e the width programmatically?
Edit: Forgot to add, the xib has a width of 400 and it seems to remain 400 width aswell.
Upvotes: 1
Views: 5525
Reputation: 3494
There are a few problems with your implementation.
First, you should not add the headerView
as subview of self.view
.
Second, if you have more than one sections, you would need a new CustomView for every section, you should not reuse it.
So your code should look something like:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return NSBundle.mainBundle().loadNibNamed("CustomHeader", owner: nil, options: nil)[0] as? UIView
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
}
You don't need any frame manipulation. Just make sure you return a correctly initialized CustomHeader
in the viewForHeaderInSection
and everything should work fine.
If you need more help or support, just let me know.
This is a small code snippet that I used to test - the only difference to your situation is that you load the headerView from the xib:
override func viewDidLoad (){
headerView = UIView.new() // here you should have your xib loading
var insideView = UIView.new();
insideView.setTranslatesAutoresizingMaskIntoConstraints(false)
headerView.addSubview(insideView);
// This is simulating the constraints you have in your xib
headerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[view(50)]-|", options: nil, metrics: nil, views: ["view": insideView]))
headerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[view]-|", options: nil, metrics: nil, views: ["view": insideView]))
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return headerView
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
}
Upvotes: 6