Swift - How dynamically fixed UITableViewHeaderFooterView height size? - ios

I have just tried below lines of code, but I doesn't work correctly. I wonder that how can I provide this case for header or footer programmatically, may be using autolayout I don't know exactly which one solved my problem. I'm using xib file both of UITableViewHeaderFooterView.
If someone explain I would be great.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Dynamic sizing for the footer view
if let footerView = tableView.tableFooterView {
let height = footerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
var footerFrame = footerView.frame
if height != footerFrame.size.height {
footerFrame.size.height = height
footerView.frame = footerFrame
tableView.tableFooterView = footerView
}
}
}

The UITableView calculates the HeaderFooter before they displayed, you can't update that height without calling reloadData() again.
Have you tried to use AutoLayout on those HeaderFooterViews?
I would set up the view from xib with the right constraint, and then:
self.tableView.estimatedSectionHeaderHeight = 100
self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension

Related

Autolayout working wrong

I'm working on profile screen, there is a UITableView inside the ViewController and I placed all user info inside the UITableView Header. To make screen more accurate due to different sizes of "About" label I use Autolayout with this code:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
sizeHeaderToFit()
}
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
}
Everything works fine, but the last string of About label is not showing, text interrupts (I set word wrap):
Add a height constraint on tableview header and try to change height constraint where you are changing frame. As you are using autolayout so you should play with the constraints rather than playing directly with the frames
you can follow this tutorial
https://useyourloaf.com/blog/variable-height-table-view-header/
Hope it will help you.

How to dynamically resize xib according to UITextView

I am using auto layout.
I am loading UIView from xib.
All elements have static size except UITextView.
I've disabled scroll on UITextView
UITextView is filled with the text of different size on ViewDidLoad(). So it can be 1 line or 7 lines there for example.
I am loading this UIView with the following method:
fileprivate func setTableHeaderView() {
guard let _headerView = UINib(nibName: "TableHeaderView",
bundle: nil).instantiate(withOwner: self, options: nil)[0] as? UIView else { return }
tableView.tableHeaderView = UIView(frame:
CGRect(x: 0, y: 0, width: tableView.frame.width, height: _headerView.frame.size.height))
configureViewController() // here I set the text for UITextView
tableView.tableHeaderView?.addSubview(_headerView)
}
When I load this UIView the height is always the same both before and after layoutSubviews. Actually the size always is equal to the initial size of the xib that is set in the Size Inspector of XCode.
I want to UITextView to fit the text size and to have different xib UIView size that will depend on the size of UITextView + all other elements + constraints.
I've tried different ways to implement this but but none did not help. What I've tried:
to set constraints in different ways
to call layoutSubviews() forcibly and check the size of the resulted UIView
to check size of UIView after viewDidLayoutSubviews
translatesAutoresizingMaskIntoConstraints = true with autoresizingMask = .flexibleHeight
Is it possible to implement this idea in such way?
Try to override viewDidLayoutSubviewsMethod
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Dynamic sizing for the header view
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFittingSize(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
tableView.tableHeaderView = headerView
}
}
}

Cant get width of table view or table view header until after viewDidAppear

func setTableHeader(){
let headerWidth = Double(tableHeader.frame.width)
// also tried let headerWidth = Double(tableView.frame.width)
print("header width is \(headerWidth)")
}
func viewWillAppear(){ output --> 351
setTableHeader()
//also tried in View Did Appear
}
func viewDidDisappear(){ output --> 296
setTableHeader()
}
The outputs refer to what occurs when run on Iphone SE. I designed my tableview and table header with constraints in Storyboard with the Iphone 6 display. I was able to get the result I wanted by changing setTableHeader to reflect view.frame.width - (left and right constraints from storyboard), however I was wondering why I couldnt get this to work, and what the less hacky work around would be? Also I am in actuality setting the dimensions of table header's subviews inside setTableHeader, but these subviews have no constraints (programatically nor in storyboard), in case that is relevant.
Thank you.
Try this , The solution was to override UIViewController().viewDidLayoutSubviews(), get the proper size of the header view based on it’s constraints, set the frame on the header, and reset it as the table header view
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Dynamic sizing for the header view
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFittingSize(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
tableView.tableHeaderView = headerView
}
}
}
Please try to add this code to viewDidLayoutSubviews method.
All views got their actual sizes only alter layout. Method viewDidLayoutSubviews called before viewDidAppear and after viewWillAppear.

Auto size view on tableViewController

I am having a view at the top of my tableViewController. The view is called viewBackground. It is there to show the post the user clicked on and the table cells will show the comments.
What I want to do is to resize the viewBackground depending on the size of the label theLabel. I have done this in the cells by setting the label in the cells to 0 lines and by implementing this little code :
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 205
How do I do the same with my viewBackground?
This is a picture of the tableView:
You can create table view with two sections. First section will contain selected post; second section - comments. If you need, i can provide some code.
Added this code and it helped!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFittingSize(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
}
}
}
I suggest to make a header for your current tableView -instead of adding an external view above it-, and then you can follow this answer, it should helps you of how you can calculate the label's string height and returning it in the tableView(_:heightForRowAt:) method.
Hope this helped.

UITableView tableHeaderView using autolayout height too small

I'm trying to create a UITableView with a header view using autolayout using storyboards. It looks fine in Xcode, but when I run the app, it does not look the same.
In Xcode:
In the app:
The image has a constraint for 150x150, and there are 8-high constraints between the top-image, image-middle label, middle description-label and description label-bottom.
Both labels have numberOfRows set to 0 and lineBreakMode set to ByWordWrapping.
I have tried settings the frame via:
if let headerView = self.tableView.tableHeaderView {
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
println("Setting height to \(height)")
var headerFrame = headerView.frame
headerFrame.size.height = height
headerView.frame = headerFrame
self.tableView.tableHeaderView = headerView
}
One of the original issues was that I had some erroneous constraints (that for some reason Xcode only started complaining about today), so I have removed those and set a contentHuggingPriority of 252 (higher than all others) on the app name label. When I resize the header view manually in the storyboard the image and app name label stay the same height, and the description label grows. It would appear that the apps uses the size of the header in the storyboard at run time, and doesn't get the height from its children.
Answering my own question here:
There are 2 steps that seem to get this to work. The first is in ViewDidLoad, and the second is in viewDidLayoutSubviews:
var headerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
if let currentTableHeaderView = self.tableView.tableHeaderView {
currentTableHeaderView.removeFromSuperview()
}
// Setting the table header view with a height of 0.01 fixes a bug that adds a gap between the
// tableHeaderView (once added) and the top row. See: http://stackoverflow.com/a/18938763/657676
self.tableView.tableHeaderView = UIView(frame: CGRectMake(0, 0, CGRectGetWidth(self.tableView.frame), 0.01))
self.headerView = AboutTableViewHeaderView(frame: CGRectZero)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let tableHeaderView = self.headerView {
var frame = CGRectZero
frame.size.width = self.tableView.bounds.size.width
frame.size.height = tableHeaderView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
if self.tableView.tableHeaderView == nil || !CGRectEqualToRect(frame, tableHeaderView.frame) {
tableHeaderView.frame = frame
tableHeaderView.layoutIfNeeded()
self.tableView.tableHeaderView = tableHeaderView
}
}
}
Hopefully that all makes sense. The viewDidLayoutSubview code is via http://osdir.com/ml/general/2014-06/msg19399.html

Resources